重点:

  • java中多线程运行原理
  • 掌握两种线程创建方式
  • 两种创建线程方式好处和弊端
  • 掌握使用Thread类 中获取和设置线程名称的方法
  • 使用匿名内部类创建多线程
  • 描述java中线程池的运行原理
  • 线程安全问题出现的原因
  • 使用同步代码块\同步方法解决线程安全问题
  • 出现死锁的原因
  • wait方法
  • notify方法
  • 线程的五个状态

一、概述

  • 进程: 进程是指正在运行的程序。 确切的来说,当一个程序进入内存开始运行,即变成一个进程。 进程是处于运行状态的程序,并具有一定独立功能。
  • 线程: 线程是进程的一个执行单元。 负责当前进程中程序的执行。一个进程中至少有一个线程,一个进程可以是多线程的。
  • 多线程程序与单线程程序:
    • 单线程程序 : 若有多个任务只能一次执行。
    • 多线程程序 : 若有多个任务,可以同时执行。

二、多线程运行原理

  • 分时调度 : 所有线程轮流使用CPU 的使用权 , 平均分配每个线程的占用CPU时间。
  • 抢占式调度  : 优先让优先值高的线程使用Cpu , 如果线程的优先级相同 , 则随机选择一个 (**线程的随机性**)。
  • java 使用的是抢占式调度。

三、抢占式调度详解

  • 实际上 , CPU使用抢占式调度模式是在多个线程之间进行着高速的切换。 对于CPU的一个核而言 , 在某一时刻只能执行一个进程 。 而CPU在多个线程之间的切换速度相对于我们而言相当的块 , 看上去是多个线程同时执行。
  • 多线程不能提高程序的执行速度 ,  但是能提高CPU的使用率。

四、主线程

  • JVM启动后 , 必然有一个执行路径(线程)从mian方法开始 , 一直执行到main方法执行结束 , 这个线程在java中 称之为主线程。
  • 示例:
    package com.tj.ThreadTest;public class ThreadTest_01 {public static void main(String[] args) {class_01 c1 = new class_01("催化");class_01 c2 = new class_01("淑芬");c1.show();c2.show();}
    }
    class class_01{private String name;class_01(String name){this.name = name;}public void show(){for(int i= 0;i<1000;i++){System.out.println(this.name+","+i);}}
    }

五、Thread类

  • 构造方法:

    • Thread() :  创建一个新线程。
    • Thread() : 创建一个名为name的线程。
  • 常用函数:
    • start() : 使线程开始执行 , 由JVM调用Thread‘中的run方法。
    • run() : 该线程要之心的操作
    • sleep() : 在指定的毫秒数之内让当前正在执行的线程休眠(暂停执行)。
  • ’创建线程的两种方法: 
    • 将该类声明为Thread类的子类。 该类必须重写Therad类的run方法 。 创建对象 , 开启线程。 run方法相当于主线程的main方法
    • 该类实现Runnable接口:  实现run方法 , 创建Runnable子类对象并传入到某个线程的构造方法中 , 开启线程。

六、创建线程方式  --- 继承Thread类

  • 第一步: 定义一个类 , 继承Thread类
  • 第二步: 重写run方法
  • 第三步:创建子类 对象
  • 第四步: 调用start方法 , 开启线程并执行  , 此时JVM会自动调用run方法。
  • 示例: 
    package com.tj.ThreadTest;public class ThreadTest_02 {public static void main(String[] args) {//创建线程对象ThreadClass_01 ti = new ThreadClass_01("线程1");//开启线程ti.start();}
    }
    //使用继承Thread类的方式创建一个线程类
    class ThreadClass_01 extends Thread{private String name;public ThreadClass_01(String name) {this.name = name;}//重写run方法@Overridepublic void run() {for(int i =0;i<1;i++){System.out.println(name +","+i);//获取当前对象线程System.out.println(Thread.currentThread());System.out.println(Thread.currentThread().getName());}}}
    
  • 思考: run方法与start方法的区别?
    • 线程对象调用run方法不能开启线程 。 仅仅是对象调用方法 。
    • 线程对象调用start方法 ,开启线程 , 并让JVM调用run方法在开启的线程中执行。
  • 继承Therad类原理
    • Thread类用于描述线程 , 具备线程应有的功能 。
    • 创建线程的目的是为了建立程序单独执行的路径, 让多部分代码同时执行 。  也就是说线程的创建并执行 需要给定线程 执行的任务。
    • 程序中的主线程 , 任务定义在main中  。 自定义线程需要执行的任务定义在run中
    • Thread类中本身的run方法并不是我们所期望的 , 所以要重写run方法 , 重新制定线程任务。
  • 多线程图解
    • 多线程执行在栈内存中 , 其实每一个执行线程都有一片属于自己的栈内存空件 , 进行方法的弹栈和压栈。
    • 当线程任务执行完成之后 , 自动释放栈内存 , 当所有的线程执行完毕之后, 进程结束。
  • 获取线程的名称
    • currentThread() : 返回当前正在执行的线程的实例
    • getName() : 获取当前实例的名称
    • 主线程的名称 : main
    • 自定义线程的名称: Thread -0   ,如果有多个线程时 , 数字顺延。    。。。 Thread -  1 。。。。
    • 示例:
      //使用继承Thread类的方式创建一个线程类
      class ThreadClass_01 extends Thread{private String name;public ThreadClass_01(String name) {this.name = name;}//重写run方法@Overridepublic void run() {for(int i =0;i<1;i++){System.out.println(name +","+i);//获取当前对象线程System.out.println(Thread.currentThread());System.out.println(Thread.currentThread().getName());}}}
      

七、创建线程方式  --- 实现Runnable接口

  • 第一步 :定义一个类 , 实现Runnable接口
  • 第二步 :实现run方法
  • 第三步 :将该类的实例对象传入到线程的构造函数中。
  • 第四步 :开启线程
  • 示例:
    package com.tj.ThreadTest;public class ThreadTest_03 {public static void main(String[] args) {//创建实现Runnable接口的类对象ThreadClass_03 tc = new ThreadClass_03();//将实现实例一参数形式传入到Thread类的构造函数中Thread t1 = new Thread(tc);Thread t2 = new Thread(tc,"线程2");//可以指定该线程的名字//启动线程t1.start();t2.start();}
    }
    //创建实现Runnable接口的类
    class ThreadClass_03 implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"线程被执行");}}
    
  • 实现Runnable原理 , 两种方式的区别:
    • 实现Runnable接口 , 避免了单继承的局限性 , 覆盖Runnable接口中run方法 , 将线程任务定义在run方法中。
    • 只有创建Thread类对象时才能创建新的线程 , 线程任务已经被封装在RUnnable接口中 。  所以可以将实现Runnable接口的实例对象以参数的形式传到Thread构造函数中。 这样线程创建时就可以明确指定要运行的线程任务。
  • 实现Runnable接口的好处
    • 避免了单继承的局限性
    • 更加符合面向对象 。  线程分为两部分  : 线程对象 , 线程任务   ;  而继承Thread之后 , 线程对象和线程任务耦合在一起
    • 实现Runnable接口 , 将任务单独分离出类 封装成对象 , 是线程任务解耦。
  • 线程匿名内部类的使用
    • 方式一:创建线程对象 ,直接重写run方法。
    • 方式二:使用匿名内部类实现RUnnable接口后传入THread构造函数。
    • 示例 : 
      package com.tj.ThreadTest;
      //线程匿名内部类的使用
      public class ThreadTest_04 {public static void main(String[] args) {//方式一new Thread(){@Overridepublic void run() {System.out.println("线程1开启");}}.start();//方式二new Thread(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"开启");}},"线程2").start();}
      }

八、线程池

  • 概述:

    • 可以容纳多个线程的容器 , 其中的线程可以反复使用 。 省去了频繁创建线程对象的操作 。 节省资源。
  • 为什么要使用线程池?
    • 在java中如果每个请求到达都开启一个线程 , 开销是相当大的 , 在实际开发中 , 创建和销毁线程花费的时间和消耗掉的资源都相当大 , 甚至超过实际处理任务请求的时间和资源。
    • 如果JVM里创建了太多的线程 , 可能会使系统由于过度消耗内存或“”切换过度“导致系统资源不足 , 为了防止系统资源不足的情况   , 需要采取一些办法 来限定任何给定时间处理的请求 数目。
    • 宗上述两点 , 所以需要尽可能的减少线程的创建的销毁次数 , 并尽量使用已有的对象进行服务。
    • 线程池主要用于解决线程声明周期开销和系统资源不足的问题。由于请求到来的时候 ,  线程已经存在 , 所以消除了创建线程带来的延时, 立即为请求服务 。 使程序响应更快。
  • ”使用线程池的方式 ---- 实现Runnable接口
    • 通常线程池都是通过线程工厂创建 , 在调用线程池中的方法和数据 , 通过线程去执行任务 。
    • 创建线程池
      • Executors线程池创建工厂类
      • ExecutorService 线程池类
      • Furture接口   用来记录线程任务执行完毕后产生的结果
    • 使用线程池的步骤:
      • 创建线程池对象
      • 创建Runnable子类对象
      • 提交Runnabel子类对象
      • 关闭线程池
    • 示例: 
      package com.tj.ThreadTest;import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;/*** 使用线程池方式 --- Runnable* */
      public class ThreadTest_05 {public static void main(String[] args) {//创建线程池对象,  指定包含几个线程。ExecutorService es = Executors.newFixedThreadPool(3);//创建实现Runnable接口的子类对象ThreadClass_05 t5 = new ThreadClass_05();//提交线程任务es.submit(t5,"周教练");es.submit(t5,"吴教练");es.submit(t5,"正教练");es.submit(t5,"赵教练");es.submit(t5,"王教练");/*注意: submit 方法调用结束后,程序并不终止,因为线程池控制了线程的关闭*将使用完的线程有归还到线程池中 * *///关闭线程池es.shutdown();}
      }
      class ThreadClass_05 implements Runnable{@Overridepublic void run() {System.out.println("我需要一个教练");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("教练来了"+Thread.currentThread().getName());System.out.println("叫我游泳之后教练回到了游泳池!");}}
  • 使用线程池方式  --- Callable接口
    • Callable 接口 : 与Runnable接口功能相似 。 用类指定线程任务 ,  其中call方法 用来返回线程任务执行后返回的结果   , call方法可以抛出异常。
    • ExecutorService : 线程池类 , 获取一个线程池对象 , 并执行线程的call方法
    • Future接口 : 用来记录线程对象执行完毕之后产生的结果 。
    • 使用线程池对象的步骤:
      • 创建线程池对线
      • 创建Callable子类对象
      • 提交Callable子类对象
      • 关闭线程池
    • 示例:
      package com.tj.ThreadTest;import java.util.concurrent.Callable;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.Future;/*** 使用线程池方式 -- callable* */
      public class ThreadTest_07 {public static void main(String[] args) throws InterruptedException, ExecutionException {//创建线程池ExecutorService es = Executors.newFixedThreadPool(2);//创建县线程任务ThreadDemo_07 t1 = new ThreadDemo_07();//提交线程任务Future<String> submit = es.submit(t1);System.out.println(submit.get());//关闭线程池es.shutdown();}
      }
      class ThreadDemo_07 implements Callable<String> {@Overridepublic String call() throws Exception {return "绝对符合国家";}}
      
    • 线程池练习: 返回两个数相加的结果
      package com.tj.ThreadTest;import java.util.concurrent.Callable;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.Future;/*** 线程池练习 ,返回两个数相加的结果* */
      public class ThreadTest_08 {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService es = Executors.newFixedThreadPool(2);ThreadDemo_08 t1  = new ThreadDemo_08(1, 1);ThreadDemo_08 t2  = new ThreadDemo_08(6, 1);ThreadDemo_08 t3  = new ThreadDemo_08(3, 1);ThreadDemo_08 t4  = new ThreadDemo_08(2, 1);Future<Integer> s1 = es.submit(t1);Future<Integer> s2 = es.submit(t2);Future<Integer> s3 = es.submit(t3);Future<Integer> s4 = es.submit(t4);System.out.println(s1.get());System.out.println(s2.get());System.out.println(s3.get());System.out.println(s4.get());es.shutdown();}
      }
      class ThreadDemo_08 implements Callable<Integer>{int a = 0,b = 0;public ThreadDemo_08(int a, int b) {this.a = a;this.b = b;}@Overridepublic Integer call() throws Exception {return a+b;}}
  • 线程同步
    • 同步代码块

      • 同步代码块 中的锁对象可以是任意对象 ,  但是要使多个线程同步时,需要使用同一个锁对象 , 才能保证线程安全。
    • 同步方法
      • 在方法声明上添加 synchronized
      • 同步方法的锁对象就是this
      • 静态同步方法的锁对象是: 类名.class
    • 线程不安全示例:
      package com.tj.ThreadTest;/*** 电影院卖票* 本场共100张票* 多个窗口同时卖票* */
      public class ThreadTest_09 {public static void main(String[] args) {ThreadDemo_09 t = new ThreadDemo_09();new Thread(t,"窗口1").start();;new Thread(t,"窗口2").start();;new Thread(t,"窗口3").start();;new Thread(t,"窗口4").start();;}
      }
      class ThreadDemo_09 implements Runnable{int ticket = 100;@Overridepublic void run() {//模拟卖票while(ticket>=0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在卖票,余票:"+ --ticket);}}/*** 出现了错误的情况 , 线程不安全* 窗口4正在卖票,余票:1窗口3正在卖票,余票:-1窗口1正在卖票,余票:0窗口2正在卖票,余票:-2* */
      }
    • 同步代码块示例:
      package com.tj.ThreadTest;
      /*** 同步代码块解决 线程安全问题* */
      public class ThreadTest_10 {public static void main(String[] args) {ThreadDemo_10 t = new ThreadDemo_10();new Thread(t,"窗口一").start();new Thread(t,"窗口二").start();new Thread(t,"窗口三").start();}}
      class ThreadDemo_10 implements Runnable {int  ticket = 10;//创建锁对象Object lock  =new Object();@Overridepublic void run() {synchronized (lock) {while(ticket>0){try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在售票,余票"+ --ticket);}}}}
    • 同步方法示例:
      package com.tj.ThreadTest;
      /*** 同步方法解决线程安全问题* * */
      public class ThreadTest_11 {public static void main(String[] args) {ThreadDemo_11 t = new ThreadDemo_11();new Thread(t,"窗口一").start();new Thread(t,"窗口二").start();new Thread(t,"窗口三").start();}
      }
      class ThreadDemo_11 implements Runnable {int  ticket = 10;//同步方法//同步方法的锁对象就是this// 静态同步方法的锁对象的 : 类名.class@Overridepublic  synchronized void run() {while(ticket>0){try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在售票,余票"+ --ticket);}}}
      
  • 死锁
    • 同步锁使用的弊端 : 当线程中出现 多个同步(多个锁)时 , 如果同时嵌套了其他的同步 , 容易 引起 一种现象: 程序 无限等待 , 这种现象叫死锁。
    • 示例:
      package com.tj.ThreadTest;import java.util.Random;/*** 线程任务中出现多个同步时* 发生死锁的情况* */
      public class ThreadTest_12 {public static void main(String[] args) {ThreadDemo_12 t = new ThreadDemo_12();new Thread(t).start();new Thread(t).start();}
      }
      //定义锁对象
      class MyLock_12{public static final Object lockA = new Object();public static final Object lockB = new Object();
      }
      class ThreadDemo_12 implements Runnable{@Overridepublic void run() {int x = new Random().nextInt(1); // 0~1if(x%2 == 0){synchronized (MyLock_12.lockA) {System.out.println("if-lockA");synchronized (MyLock_12.lockB) {System.out.println("if - lockB");System.out.println("if 大口吃肉");}}}else{synchronized (MyLock_12.lockB) {System.out.println("if-lockB");synchronized (MyLock_12.lockA) {System.out.println("if - lockA");System.out.println("else 大口吃肉");}}}x++;}}
      
  • Lock接口
    • 常用方法 :

      • Lock() : 获取锁对象 。
      • unlock() : 释放锁
      • 示例:
        package com.tj.ThreadTest;import java.util.concurrent.locks.Lock;
        import java.util.concurrent.locks.ReentrantLock;/*** 使用Lock接口 * 改进卖票程序* */
        public class ThreadTest_13 {public static void main(String[] args) {MyTicket_13 mt = new MyTicket_13();new Thread(mt , "窗口一").start();new Thread(mt , "窗口二").start();
        //      new Thread(mt , "窗口三").start();
        //      new Thread(mt , "窗口四").start();
        //      new Thread(mt , "窗口五").start();
        //      new Thread(mt , "窗口六").start();}
        }
        class MyTicket_13 implements Runnable{int ticket = 10;//创建锁对象Lock l = new ReentrantLock();@Overridepublic void run() {//获取锁l.lock();while(ticket>0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在卖票,余票:" + --ticket);}//释放锁l.unlock();}}
  • 等待唤醒机制
    • 线程之间的通讯 : 多个线程在处理同一个资源 , 但处理的动作不同。
    • 等待唤醒机制 : 通过 一定的手段使各个线程能有效的利用资源 。
    • 常用方法:
      • wait() : 等待 , 将正在执行的线程释放其执行资格和执行权 ,并 存储在线程池中 。
      • notify() : 唤醒 , 唤醒线程池中被wait的线程 , 一次唤醒一个 , 而且是任意的 。
      • notifyAll() : 唤醒所有 , 将线程池中所有被wait的线程唤醒。
      • 这些方法都定义在Object 中  , 因为:使用 时必须明确指定所属的锁 , 而锁又可以是任意对象  , 所以能被任意对象调用的方法一定定义在Object中 。
      • 示例:
        package com.tj.ThreadTest;
        /*** 线程中等待唤醒机制实例* 等待唤醒机制,使多个线程之间有效利用资源。* 输入线程想Resource 中输入name ,sex ,输出线程从资源中输出* 1. 档input发现resource中没有数据时 ,开始输入,输入完成后叫outPut输出,如果已有数据 则wait* 2. 档output发现Resource中没有数据时 ,就wait ,有数据时唤醒输出后叫input输入* */
        public class ThreadTest_14 {public static void main(String[] args) {//资源对象Resours_14 r = new Resours_14();//任务对象Input in  = new Input(r);Output out = new Output(r);//开启线程new Thread(in).start();new Thread(out).start();}
        }
        //模拟资源类
        class Resours_14{private String name ;private String sex ;private boolean flag = false;public synchronized void in(String name ,String sex ){//如果有值 ,则wait状态   ,等待输出if(flag)try {wait();} catch (InterruptedException e) {e.printStackTrace();}//设置成员变量this.name = name;this.sex = sex;//设置之后 Resource 中有值 将flag置为trueflag = true;//唤醒outputthis.notify();}public synchronized void  out(){//如果没有值 ,则进入等待状态  ,登台输入if(!flag)try {wait();} catch (InterruptedException e) {e.printStackTrace();}//将数据输出System.out.println("姓名:" + name +"性别: "+sex);//改变标记flag = false;//唤醒input  ,进行数据输入this.notify();}
        }
        //输入线程任务类
        class Input implements Runnable{private Resours_14 r ;public Input(Resours_14 r) {this.r = r;}@Overridepublic void run() {int count = 0;while (true){//降低CPU压力  try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}//交替设置资源if(count == 0){r.in("小明", "男");}else{r.in("小花", "女");}//两个数据之间相互切换count = (count +1) %2;}}
        }
        //输出线程任务类
        class Output implements Runnable{private Resours_14 r ;public Output(Resours_14 r) {super();this.r = r;}@Overridepublic void run() {while(true){//降低CPU压力  try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}//输出资源内容r.out();}}}
  • 补充: wait() 与 sleep() 的区别 : 
    • wait() : 释放锁对象 , 释放CPU使用权 , 在休眠时间内能被唤醒 。
    • sleep() : 不释放锁对象 , 释放CPU使用权 , 在休眠时间内不能被唤醒

九、线程安全

  • 如果有多个线程同时运行同一段代码,程序每次运行结果和单线程运行的结果是一样的,而且其他的变量值也与预期是一样的,那么就是线程安全的。

  • 线程的安全问题都是由全局变量和静态变量引起的,每个线程对全局变量和局部变量只有读操作而没有写操作,一般来说这个线程就是安全的;若多个线程同时执行写操作,一般都是需要考虑线程同步,否则的话可能影响线程安全。

  • 示例:

    /*** 线程同步的两种方式 1. 同步代码块 2. 同步方法 示例: 电影院买票 共有100张票 ,三个窗口同时买票* */
    public class ThreadDemo_09 {public static void main(String[] args) {new Thread(new ThreadTest_09_01(),"窗口一").start();new Thread(new ThreadTest_09_01(),"窗口二").start();new Thread(new ThreadTest_09_01(),"窗口三").start();}
    }class ThreadTest_09_01 implements Runnable {private static int ticket = 100;@Overridepublic void run() {while (1 == 1) {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "出票,余票"+ --ticket);}}}}
    结果:
    窗口一出票,余票99
    窗口三出票,余票98
    窗口二出票,余票99//与窗口一重复   ,线程不安全
    窗口二出票,余票95
    窗口三出票,余票96
    窗口三出票,余票93
    窗口三出票,余票92
    窗口一出票,余票97
    窗口二出票,余票94
    窗口一出票,余票91
    窗口二出票,余票90
    。。。。

    十、线程同步

    • java中处理线程同步 的两种方式:

      • 同步代码块
      • 同步方法
    • 同步代码块: 在代码块声明上加上synchronized     且要使用同一锁对象才能保证线程同步。.
    • 同步方法   : 在方法属性上加synchronized  。

    十一、守护线程

    • 守护其他线程的执行。

    • 当被守护的线程结束时 , 无论守护线程是否执行完毕则随之结束 。

    • 只要代码中出现了线程要么是守护线程 , 要么是被守护的线程 。

    • 如果出现率多个被守护的线程 , 则以最后一个被守护的线程结束为标志而结束 。

    • gc(垃圾回收机制)本质上就是一盒

    • //设置为守护线程
          t.setDaemon(true);

    十二、 线程的优先级

    • 线程有1~10   10个优先级 。
    • 数字越大 , 优先级越高 , 理论上优先级越高的线程越容易抢到cpu执行权 , 但是相邻的两个优先级之间差别不大, 至少相差五个优先级才能看出效果 。
    • 如果不设置优先级 , 则默认的优先级为5 。

Java 多线程Thread相关推荐

  1. Java多线程-Thread、Runnable、Executor

    线程分为五个阶段:创建.就绪.运行.阻塞.终止. 创建:新建一个线程对象,如Thread thd=new Thread(). 就绪:创建了线程对象后,调用了线程的start()方法(此时线程只是进入了 ...

  2. Java多线程——Thread Runnable源码解析

    Java多线程的两种实现方法大家都应该知道了:继承Thread的子类实例化和实现Runnable接口用这个接口实现类去创建Thread实例. Java的线程在Linux平台上使用的是NPTL机制,JV ...

  3. JAVA多线程Thread VS Runnable详解

    进程与线程 进程是程序在处理机中的一次运行.一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立.所以进程是重量级的任务,它们之间的通信和转换都需要操作系统 ...

  4. Java多线程 - Thread和Runnable的区别

    在这我们就不在讲解Thread和Runnable的用法,如果不会的可以去看上一篇文章:<Java实现多线程的几种方式> Runnable是接口. Thread是一个类,继承了Runnabl ...

  5. Java多线程(Thread)间通信和共享数据

    多线程间如何通信和共享数据,肯定好多小伙伴都不知道, 或者很久之前知道,现在已经忘却,现在我和大家一起复习一下. 一.线程间通信 1.线程间通信:A执行完,B才执行 /*** 线程间通信:A执行完,B ...

  6. java多线程thread使用_Java多线程——thread及runnable的基本使用及交替执行

    /*** Created by LiuHuiChao on 2016/3/11.*/public classActor extendsThread { @Overridepublic voidrun( ...

  7. Java多线程-Thread常用方法

    sleep() 线程休眠 使当前线程休眠,但不会释放对象的同步锁: 运行状态 -> 休眠(阻塞状态): 线程休眠的时间大于指定的休眠时间就会重新被唤醒,阻塞状态 -> 就绪状态,从而等待C ...

  8. java多线程-- thread.setPriority() 线程优先级

    线程优先级 不设置优先级,默认为 5 先设置,在启动!!! 优先级只是相对的,大概率下是优先级高的先执行,不是一定先执行 package cn.usts.edu.lesson06;/*** 线程优先级 ...

  9. java多线程学习-java.util.concurrent详解

    http://janeky.iteye.com/category/124727 java多线程学习-java.util.concurrent详解(一) Latch/Barrier 博客分类: java ...

最新文章

  1. IntelliJ IDEA 2021.1正式发布!快来看看又有哪些神仙功能加入!
  2. [云炬创业基础笔记]第一章创业环境测试11
  3. Qt下使用QtSql连接sqlite3所遇到的问题总结
  4. 利用ffmpeg转换mp4文件
  5. android XMl 解析神奇xstream 四: 将复杂的xml文件解析为对象
  6. 使用异步任务加载网络上的图片
  7. 对C#开发两个基本原则的深入讨论
  8. 在乌镇拼命“洗白”的拼多多
  9. #语音信号处理基础(十一)——梅尔倒谱系数的提取
  10. [转]Ogre:Hardwarebuffer
  11. 《算法第四版》环境搭建
  12. 让“王码五笔输入法”成为你的专用输入法!
  13. zuc算法代码详解_ZUC祖冲之序列密码算法
  14. Win10磁盘管理教程:新建、合并分区,添加和修改盘符
  15. Python进阶之Scrapy抓取阳光政务平台
  16. IDEA将后端代码上传至远程服务器
  17. Just For Fun
  18. 矩阵的特征值、特征向量、特征子空间
  19. “临沂公众号推广平台”的操作流程是怎样的?
  20. CS0533隐藏继承的抽条成员/CS0534不实现继承的抽象成员

热门文章

  1. schedule execution
  2. 读《JavaScript dom编程艺术(第2版)》笔记 1-2
  3. 【小菜日志】用C#完成Allen Lee's Magic大虾推荐的F#作业F#学习中
  4. powergrep linux版本,PowerShell实现简单的grep功能
  5. Oracle数据库备份报错12514,Oracle数据库备份导出时,出错:ORA-12514
  6. php xml 四种,xml中常见的四种解析方式是什么?
  7. Rainmeter 天气
  8. 尚学python课程---11、linux环境下安装python注意
  9. 360 补天平台,也没个什么人啊。。。
  10. 【BZOJ1899】[Zjoi2004]Lunch 午餐 贪心+DP