java多线程

多线程就是多个任务同时执行

进程是对操作系统就是多任务执行,每个进程都有自己的代码和数据空间,进程是资源分配的最小单元,一个进程包括至少一个线程

线程多个线程共享代码和数据空间,线程之间切换消耗较小,线程是cpu调度的最小单位

好程序的三高:高可用(数据不会出错)高性能(效率高)高并发(多用户并发)

多线程的创建方式

1继承Thread类 重写run()方法

       执行类直接继承Thread类,内部重写run()方法,自身调用start()方法启动多线程

public class Threaddemo01 extends Thread {   //1继承Thread

    public static void main(String[] args) {

       Threaddemo01 th=new Threaddemo01();   //3创建对象以及线程

       th.start();                                //4线程就绪

       for(int i=0;i<10;i++){                  //5主方法的另一线程同步执行

           System.out.println("哭");

       }

    }

    @Override

    public void run() {                           //2重写run()方法

       for(int i=0;i<100;i++){

           System.out.println("笑");

       }

    }

}

Thread中

start()方法启动线程

              run()方法定义多线程的线程体 通过重写实现不同的代码

              run()需要通过start()启动,否则就变为方法的调用,并非多线程

              Thread属于lang包

2实现Runnable接口,重写run()方法 --推荐

优点通过类实现接口,能够避免使用extends

缺点是Runnable没有直接的start方法 没有返回值和异常抛出

主要步骤:

1创建多线程类实现接口,并重写run()  注意 :并非是使用多线程的类

2创建多线程类的对象

3开启线程需要创建Thread的静态代理

在静态代理中导入多线程类的对象,通过start()方法启动

new Thread(多线程对象,String).start();   (创建启动同步执行,能够命名线程)

普通创建

public class Threaddemo2 implements Runnable { //实现Runnable接口      

    public static void main(String[] args) {   

       Threaddemo2 th=new Threaddemo2();        //创建引用

       Thread rh =  new Thread(th);               //接入静态代理

         rh.start();                                  //代理就绪

       for(int i=0;i<10;i++){

           System.out.println("哭");

       }

    }

    @Override

    public void run() {                             //重写run方法

       for(int i=0;i<100;i++){

           System.out.println("笑");

       }

    }

}

对于只在单个类中使用的多线程类,可以写成成员内部类

对于只在单个方法中使用的多线程类,可以写成局部内部类

简化创建

针对单次并直接使用的多线程体通过匿名类或lambda表达式实现并启动

不再需要另外创建实现Runnable的类

public class Threaddemo3 {

    public static void main(String[] args) {

       new Thread(new Runnable(){                 //匿名类

           public void run() {

              for(int i=0;i<100;i++){

                  System.out.println("笑");

              }

           }

       }).start();

       for(int i=0;i<10;i++){

           System.out.println("哭");

       }

    }

}

new Thread(()->                                      //直接使用lambda表达式

{for(int i=0;i<100;i++)System.out.println("笑");}).start();

       for(int i=0;i<10;i++){

           System.out.println("哭");

       }

 

需要练习龟兔赛跑

 3实现Callable接口,重写call()方法

优点是可以返回值并抛出异常   属于juc高级多并发处理(了解即可) 

1         创建Callable的实现类,在实现类中重写call()方法,在call()中写入多线程体

class 类名 implements Callable<范型>{

       public 返回值类型 call(){

              多线程的内容

              return 返回值

}

}

2         创建线程

ExecutorService 引用名=Executors. newFixedThreadPool (线程容量);

创建多线程类的对象,获取对象名

Future<返回值类型> 返回值引用名1=引用名.submit(对象名);

Future<返回值类型> 返回值引用名2=引用名.submit(对象名);

引用名.shutdown();

线程状态

新生状态 : new,每个线程都有自己的运行空间

就绪状态 : start(),代表线程具有可运行的能力,在就绪队列中等待cpu调度

运行状态 : cpu把时间片分配给某个线程,这个线程就就行运行状态

阻塞状态 : sleep()..

终止状态 : 执行完毕

注意:      一个线程一旦阻塞状态,阻塞解除进入就绪状态并非继续执行

一旦一个线程以终止,无法恢复,如果创建开启,也是新的线程

 

终止状态的方法

       1)正常执行完毕

2)强制结束 stop(),destroy(),方法已过时,不推荐使用

3)通过标识进行控制--推荐(flag等)

进入就绪状态

1.start()

2.阻塞状态结束

3.yield()                礼让线程,当前线程进入就绪状态

4.线程切换,被切换的线程进入到就绪状态

进入阻塞状态

sleep()    用于将问题放大增加问题发生的可能性   模拟网络延时

wait()

join( thread )  被插队,等待插队线程执行完毕

IO操作

Thread中的方法

       sleep(毫秒)   静态方法

              写在多线程中,控制执行线程进入阻塞状态若干时间

       用于将增加出现问题的可能性   模拟网络延时

       yield() 静态方法

              当前线程执行到Thread.yield()时回到就绪排队状态,相当于0秒sleep

       join()

              插队线程       用于将目标线程插到其他线程的前面

              目标线程调用该方法,将调用该方法的代码插入到其他线程的代码中

使得其他线程等待目标线程先执行完成

getStatic()   

       获取指定线程的线程状态返回一个枚举类

枚举类Thread.State是Thread的内部枚举类,通过该类进行比较

       setPriority(int)

       设置线程的优先级 优先级包括1-10 默认为5

       Thread定义了静态优先级常量

       Thread.MAX_PRIORITY=10

       Thread.MIN_PRIORITY =1

    Thread.NORM_PRIORITY=5

getPriority()

获取线程的优先级

      

线程安全

多线程同时操作同一份资源,可能出现线程不安全的问题

synchronized同步锁处理方法 

锁的范围太大,效率低,锁的范围太小锁不住

1同步方法 效率较低,简单

同步静态方法

      同步成员方法

       直接在成员方法或成员变量之前加上synchronized修饰符

 

       锁静态方法,锁类的class对象都是锁类,锁住了这个类的所有对象

2同步块

       同步块锁的内容就是要线程修改的内容  也相当于钥匙

synchronized(this|类名.calss|资源(成员属性)){锁住的代码}

多线程执行到同步块时,观察锁对象是否被其他线程调用,若调用则等待

A需要锁的代码在静态方法中时,同步块需要将类全部锁上

       Synchronized(类名.class){锁住的代码}

       锁住的内容包括类的静态内容和所有该类的对象 静态环境中不能使用this

B需要锁的代码在成员方法中,同步块需要将对象锁住

Synchronized(this){锁住的代码}

锁住的内容是对象的所有成员属性

C需要锁的内容是属性,可以直接锁属性

Synchronized(属性){锁住的代码}

锁一定要锁不变的资源内容,锁的就是地址(自定义类型对象地址)

double check 双重检查 在锁内之前添加if判断 效率高,使得锁的范围小

posted @ 2019-06-15 08:20  小布大佬  阅读(163)  评论(0编辑  收藏  举报