zoukankan      html  css  js  c++  java
  • Java 多线程

    1、程序和进程:

      程序:一个固定的运算逻辑和数据的集合,是一个静态的状态,一般存储在硬盘中

      进程:正在运行的程序,是程序的一次运行,是一个动态的状态

    2、进程和线程:

      进程:一个正在运行的程序,有自己独立的资源分配,是一个独立的个体

      线程:一个独立的执行路径。多线程,一个进程中可能有许多子任务,每个线程都可以独立的完成一个子任务,各个任务之间没有依赖关系,可以单独执行。

    3、并行和并发:

      并行:多个程序同时执行,相互独立。

      并发:多个任务同时发起,但不能同时执行,只能来回切换的执行。在同一个时间段内,将每个程序都执行过。

      问题:并发到底是提升了效率还是降低了效率?

        多个任务都在执行,效率提高了,但对于某一单独任务来说是降低了。

        并发技术解决了各个设备之间速率不同的问题(如内存和硬盘的存储速度不同),大大提高了CPU的利用率。

    4、多线程实现方式(3种):

      继承方式:(代码示例)

    1. 写一个类,继承Thread
    2. 重写run()方法
    3. 创建类对象,对象.start()方法执行

      注:若使用对象.run(),则是普通的执行方法,不会开启新线程

      实现方式:(代码示例)

    1. 写一个类,实现Runnable接口
    2. 重写run()方法
    3. 创建类对象(任务对象)
    4. 创建线程对象,将任务传给线程Thread t = new Thread(任务对象名);
    5. t.start()启动线程,会自动执行run()内容

      两种方式的比较:

    1. 代码复杂程度:第一种方式更简单
    2. 实现原理

        继承Thread,调用start()方法,本质上是调用start0()方法,是本地方法,由C语言实现,java中看不到源代码

        实现Runnable接口,是创建了一个任务对象,将对象传给线程,再开启线程

       3.在设计实用性方面:

        java中继承都是单继承,如果继承了Thread,则无法继承其它类

        Java中对接口的实现可以多实现,不影响程序的编写

      匿名内部类实现方式:(代码示例)

        new Thread(){run () { } }.start();

        new Thread(new Runnable(){run () {} });

    5、多线程中的常用方法:(代码示例)

      1.获取线程的名称getName()

        注意:

        1.如果没有给线程命名,则线程名字从Thread-0开始依次增加

        2.可以使用对象的引用调用此方法,也可以在线程类中调用

        Thread.currentThread().getName()

        3.Runnable实现类中没有此方法

      2.使用对象的引用设置线程名字setName():

        构造方法也可设置线程名字:Thread(Runnable 任务名, String 线程名);

        对象名.setName(String name)

      3.获取当前线程对象Thread.currentThread()

      4.线程休眠Thread.sleep(毫秒)

        作用:当代码在某个位置需要休息时,就使用休眠

        无论哪个线程执行到这里都会休眠

        注意:有一个异常,中断异常InterruptedException,在run()中必须处理,不能声明

      5.守护线程:setDaemon(boolean flag)

        每条线程默认都不是守护线程,只有设定flag为true才会成为守护线程

        特点:守护其它非守护线程,如果其它非守护线程全都挂掉则跟随死亡

      6.设置线程的优先级setPriority()

        NORM_PRIORITY   5

        MAX_PRIORITY    10

        MIN_PRIORITY     1

    6、安全问题(同步)(代码示例:火车站购票)

      多线程在操作共享数据的时候可能会产生线程不安全问题

      解决方法:使用同步代码块

      格式:synchronized(锁对象){需要同步的代码}

      原理:在有线程处于同步代码块之中时,其它线程必须在代码块外等待,直到里面的线程运行结束

      同步方法:当一个方法中所有的代码都在同步代码块中时,可以将方法定义为同步方法

      格式:权限修饰符 synchronized 返回值类型 方法名(参数列表){方法体};

      注:非静态方法的锁对象是this,也就是当前对象

        静态方法的锁对象是 类名.class (在方法区的一个对象)

        如果两条线程操作相同的数据,锁对象必须保持一致

        使用什么锁,一般用保护的数据作为锁对象

    7、死锁

      A线程需要甲资源,同时拥有了乙资源,B线程拥有乙资源,同时需要甲资源,两条线程都不肯释放自己的资源,就会形成死锁。

      有了同步代码块的嵌套,就可能发生死锁。某条线程获取了外层的锁对象A,需要内层的锁对象B,等待;另外一条线程获取了外层的锁对象B,需要内层的锁对象A,等待。两条线程就会形成死锁。

    public class Demo01 {
        //第一种方式:继承Thread,重写run方法,创建对象,对象.start()
        public static void main(String[] args) {
            SellTicket st = new SellTicket();
            SellTicket st1 = new SellTicket();
            SellTicket st2 = new SellTicket();
            st.start();
            st1.start();
            st2.start();
            
        }
    
    }
    class SellTicket extends Thread{
        static int count=100;//使用静态属性共享票数
        @Override
        public void run() {
            while(true){
                if(count>0) {
                    System.out.println(this.getName());
                    String name = Thread.currentThread().getName();
                    System.out.println(name+"...卖出了第"+count--+"张票");
                }else {
                    break;
                }
            }
        }
    
    }
    多线程第一种方式
    public class Demo02 {
        //第二种方式:实现Runnable接口,重写run方法,创建类对象(任务对象)
        //创建线程对象并将任务对象传给线程,线程对象.start()启动    
        public static void main(String[] args) {
            MyTicket mt = new MyTicket();
            Thread t1 = new Thread(mt,"窗口1");
            Thread t2 = new Thread(mt,"窗口2");
            Thread t3 = new Thread(mt,"窗口3");
            t1.start();
            t2.start();
            t3.start();
            
        }
    
    }
    class MyTicket implements Runnable{
        int count = 100;
        @Override
        public void run() {
            while(true){
                if(count>0) {
                    
                    String name = Thread.currentThread().getName();
                    System.out.println(name+"...卖出了第"+count--+"张票");
                }else {
                    break;
                }
            }
            
        }
    }
    多线程第二种方式
    public class Demo03 {
        //第三种方式:匿名内部类
        public static void main(String[] args) {
            new Thread(new MyTicketWindow()).start();
            new Thread(new MyTicketWindow()).start();
            new Thread(new MyTicketWindow()).start();
    
        }
    
    }
    class MyTicketWindow implements Runnable{
        static int count = 100;
        static Object obj = new Object();
        @Override
        public void run() {
            while(true){
                synchronized (obj) {
                    if(count>0) {
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        String name = Thread.currentThread().getName();
                        System.out.println(name+"...卖出了第"+count--+"张票");
                    }else {
                        break;
                    }
                }
                
            }
            
        }
    }
    多线程第三种实现方式
  • 相关阅读:
    Codeforces Round #592 (Div. 2)C. The Football Season(暴力,循环节)
    Educational Codeforces Round 72 (Rated for Div. 2)D. Coloring Edges(想法)
    扩展KMP
    poj 1699 Best Sequence(dfs)
    KMP(思路分析)
    poj 1950 Dessert(dfs)
    poj 3278 Catch That Cow(BFS)
    素数环(回溯)
    sort与qsort
    poj 1952 buy low buy lower(DP)
  • 原文地址:https://www.cnblogs.com/xfdhh/p/11254482.html
Copyright © 2011-2022 走看看