Thread.State类
Thread.State
线程状态。 线程可以处于以下状态之一:
NEW
- 尚未启动的线程处于此状态。
RUNNABLE
- 在Java虚拟机中执行的线程处于此状态。
BLOCKED
- 被阻塞等待监视器锁定的线程处于此状态。
WAITING
- 正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITING
- 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED
- 已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。
线程之间的通信
-
等待唤醒案例:线程之间的通信
/* Object类中的方法: wait(),导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。 notify(),唤醒正在等待对象监视器的单个线程。 */ wait() Object obj=new Object(); new Thread(){ @Override public void run() { // 保证等待和唤醒的进程只能有一个执行 synchronized (obj){ System.out.println("正在执行的线程"); // 执行顺序1 try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } // 唤醒后执行的代码 System.out.println("执行唤醒后的线程"); // 执行顺序3 } } }.start(); new Thread(){ @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj){ System.out.println("唤醒等待执行的线程"); // 执行顺序2 obj.notify(); // 随机唤醒等待的线程中的一个 } } }.start();
-
进行TimeWaiting(计时等待)
/* 进行TimeWaiting(计时等待)的两种方式 1、使用sleep(long m)方法,在毫米值结束之后,线程睡醒进入到Runnable/Blocked状态 2、使用wait(long m)方法,在毫米值结束后,线程还没有被notify唤醒就会自动醒来, 线程睡醒进入到Runnable/Blocked状态 */ public static void main(String[] args) { Object obj=new Object(); new Thread(){ @Override public void run() { // 保证等待和唤醒的进程只能有一个执行 synchronized (obj){ System.out.println("正在执行的线程"); try { obj.wait(5000); } catch (InterruptedException e) { e.printStackTrace(); } // 唤醒后执行的代码 System.out.println("执行唤醒后的线程"); } } }.start(); }
public static void main(String[] args) { Object obj=new Object(); new Thread(){ @Override public void run() { // 保证等待和唤醒的进程只能有一个执行 synchronized (obj){ System.out.println("正在执行的线程1"); try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } // 唤醒后执行的代码 System.out.println("执行唤醒后的线程1"); } } }.start(); new Thread(){ @Override public void run() { // 保证等待和唤醒的进程只能有一个执行 synchronized (obj){ System.out.println("正在执行的线程2"); try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } // 唤醒后执行的代码 System.out.println("执行唤醒后的进程2"); } } }.start(); new Thread(){ @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj){ System.out.println("唤醒等待执行的线程"); obj.notifyAll(); // 唤醒所有等待的线程 } } }.start(); }
-
线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)不同
多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务, 并且我们希望他们有规律的执行, 那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。 -
等待与唤醒机制:就是在一个线程进行了规定操作后,就进入等待状态(wait), 等待其他线程执行完他们的指定代码过后 再将其唤醒(notify)。即多个线程在操作同一份数据时, 避免对同一共享变量的争夺。
/* 调用notify方法: 如果能获取锁,线程从WAITING状态变为RUNNABLE状态; 否则线程从wait set出来,又进入entry set,线程从WAITING状态变为BLOCK状态 */ /* 调用wait和notify方法需要注意的事项: I、必须有同一个锁对象调用 II、都是Object类的方法 III、都必须在同步代码块或者同步函数中使用 */
public class BaoZi { String pi; String xian; boolean flag=false; }
public class BaoZiPu extends Thread{ private BaoZi bz; public BaoZiPu(BaoZi bz){ this.bz=bz; } @Override public void run() { int count=0; while (true) { synchronized (bz) { if (bz.flag == true) { try { bz.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (count % 2 == 0) { bz.pi = "薄皮"; bz.xian = "三鲜"; } else { bz.pi = "冰皮"; bz.xian = "牛肉大葱"; } count++; System.out.println("包子铺正在生产:" + bz.pi + bz.xian + "包子"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } bz.flag = true; bz.notify(); System.out.println("包子已经生产好了"); } } } }
public class ChiHuo extends Thread { private BaoZi bz; public ChiHuo(BaoZi bz){ this.bz=bz; } @Override public void run() { while (true){ synchronized (bz){ if(bz.flag==false){ try { bz.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("吃货正在吃"+bz.pi+bz.xian+"包子"); bz.flag=false; bz.notify(); System.out.println("吃货已经把包子吃完了,包子铺开始生成包子"); System.out.println("------------"); } } } }
public class demo { public static void main(String[] args) { BaoZi bz= new BaoZi(); new BaoZiPu(bz).start(); new ChiHuo(bz).start(); } }
线程池
- 概述:容纳道光线程的容器–> 集合(ArrayList,HashSet,LinkedList,HashMap)
- Executors类:工厂和工具方法Executor , ExecutorService , ScheduledExecutorService , ThreadFactory和Callable此包中定义的类。是线程池的工程类
- Executors的静态方法
3.1 newFixedThreadPool(int nThreads),创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程。/* 参数: int nThread--创建线程池中包含的线程数量 返回值: ExecutorService接口,返回的是ExecutorService接口的实现类对象,可以使用ExecutorService接口来接收(面向接口编程) ExecutorService:线程池接口,用来从线程池中获取线程,调用start方法,执行线程任务。 submit(Runnable task) 提交一个可运行的任务执行,并返回一个表示该任务的未来。 线程池的使用方法: 1、使用线程池的工厂类Executors里面的newFixedThreadPool生成一个指定线程数量的线程池 2、创建一个类,实现Runable接口,重写run方法,设置线程任务 3、调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程执行run方法 4、调用ExecutorService中的shutdown方法,销毁线程池。 shutdown(),启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务。 */ // 1. ExecutorService es= Executors.newFixedThreadPool(2); // 3. es.submit(new RunableImpl()); // pool-1-thread-1创建了新线程 es.submit(new RunableImpl()); // pool-1-thread-2创建了新线程 es.submit(new RunableImpl()); // // pool-1-thread-2创建了新线程 // 4. es.shutdown
// 2. public class RunableImpl implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"创建了新线程"); } }