day11多线程

来源:互联网 发布:淘宝汽车配件保证金 编辑:程序博客网 时间:2024/06/05 19:38

day11多线程:

  • [ ] 进程:当前正在运行的程序,一个应用程序在内存中的执行区域。
  • [ ] 线程:进程中的一个执行控制单元,进行路径

    ​一个进程可以有单个到多个线程。

  • [ ] 单线程:安全性高,效率低

  • [ ] 多线程:。。。低,。。高。

多线程的实现:

Thread类:

​ 实现Runnable接口:
​ 构造方法:

new Thread();new Thread(Runnable r);可以传入实现了该接口的类。

创建新线程的方法:(继承)

​ 1, 定义一个类 继承 Thread
​ 2, 重写 run() 方法
​ 3, 把线程要做的事情(代码)写在该方法里
​ 4, 在主方法里创建 Thread 的子类对象
​ 5, 调用 start() 启动线程

​ 注意:
​ 不可以调用 run()
​ 并没有开启多条线程

class MyThread extends Thread{        void run(){            //需要执行的代码。        }    }    Test{        main(){            MyThread mt = new MyThread();            mt.start;        }    }

Thread类一般方法:

String getName();获取线程名。void setName(String s);修改线程名。

创建新线程的方法2:(实现)

​ 1>声明一个类实现Runnable接口
​ 2>重写该接口的run()方法
​ 3>在主方法中创建一个或多个实例
​ 4>创建新的线程对象,将实例作为参数传入线程的构造方法(这是为了线程对象可以使用Thread的静态方法)。
​ 5>调用线程的start()
注意:

Thread.currentThread();是Thread类的静态方法,获取当前线程对象(是一个Thread对象)。获取该对象后,可以继续调用Thread的方法。static void sleep(long millis)当前线程休眠。

​ 在run()方法中,可以定义一个用于计数器的局部变量。当不同的线程执行run方法时,可以分别统计不同线程执行的计数器。并在run方法内打印输出,各个线程都会分别执行对应的计数器打印输出。

多个线程并发访问同一个数据时,会出现不安全的问题。

synchronizes同步

​ 可以修饰代码块和方法,被修饰的代码一旦被某个线程访问,直接锁上,其他线程无法访问。

同步代码块

格式:

synchronizes(锁对象){}

注意事项:
- [x] 锁对象需要被所有线程共享。锁对象是在类中创建一个共享的对象即可。Object o = new Object();将o作为锁对象传入同步代码块。(这种方式只针对于实现Runnable接口的方法,不能创建多个线程的对象,)
- [x] 同步代码块不要加在了循环体的外面,否则只有一个线程可以进入循环。
- [x] 锁对象要保证是同一个对象,不能是多个。
- [x] 如果是用继承Thread的方式实现多线程共享数据,那么共享数据必须声明是静态的,同步锁也需要设置是静态的,唯一的。因为在主线程中会产生多个该实现类来实现多线程,必须共享该类的静态成员。

同步方法:

​ 使用关键字synchronized修饰的方法,一旦被一个线程访问,则整个方法全部锁住,其他线程则无法访问

注意事项:

使用关键字synchronized修饰的方法,一旦被一个线程访问,其他线程不能访问。将同步代码块中的代码抽取为方法,然后将方法的调用放在同步代码块中或者将方法的声明中定义为synchronizes的,即同步方法同步方法的锁对象是默认的,非静态同步方法是this.调用方法当前对象的引用。静态方法同步对象是.class对象,即当前类的字节码文件。

死锁

​ 基本上都是由于 同步代码块的嵌套使用 导致的

​ 死锁: (有可能在面试的时候,让你手写!!!)
​ 大家以后在实际开发,一定要避免出现 这种嵌套的使用

class MyRun implements Runnable {    int num = 0;    //准备两把锁    String s1 = "老王";    String s2 = "小王";    @Override    public void run() {        while(true){            if(num % 2 == 0){                //线程1进来了                //同步代码块的嵌套                synchronized (s1) {//线程2进来了                    //线程2 拿到了 s1 进来了...                    System.out.println(Thread.currentThread().getName()+"拿到了"+s1+num);                    synchronized (s2) {//线程1进来了                        System.out.println(Thread.currentThread().getName()+"拿到了"+s2+num);                    }//s2的右大括号                }//s1的右大括号            }else{                //同步代码块的嵌套                synchronized (s2) {//线程 1进来了... 意味着拿到了 小王...                    System.out.println(Thread.currentThread().getName()+"拿到了"+s2+num);                    //线程1 失去了cpu的执行权,处于等待的状态...                    synchronized (s1) {                        System.out.println(Thread.currentThread().getName()+"拿到了"+s1+num);                    }                }            }            //不管走if还是else 都让num++            num++; //1        }    }}










原创粉丝点击