zoukankan      html  css  js  c++  java
  • 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判断 效率高,使得锁的范围小

  • 相关阅读:
    标签的讲解
    属性分类
    LeetCode 003. 无重复字符的最长子串 双指针
    Leetcode 136. 只出现一次的数字 异或性质
    Leetcode 231. 2的幂 数学
    LeetCode 21. 合并两个有序链表
    象棋博弈资源
    acwing 343. 排序 topsort floyd 传播闭包
    Leetcode 945 使数组唯一的最小增量 贪心
    Leetcode 785 判断二分图 BFS 二分染色
  • 原文地址:https://www.cnblogs.com/javaxiaobu/p/11026359.html
Copyright © 2011-2022 走看看