JAVA进阶26(多线程/01)
1、 线程概念
线程被称为轻量级进程,是程序执行的最小单位,它是指在程序执行过程中,能够执行代码的一个执行单位。每个程序程序都至少有一个线程,也即是程序本身。
2、线程状态
Java语言定义了5种线程状态,在任意一个时间点,一个线程只能有且只有其中一个状态。
(1)新建(New):创建后尚未启动的线程处于这种状态
(2)运行(Runable):Runable包括了操作系统线程状态的Running和Ready,也就是处于此状态的线程有可能正在执行,也有可能正在等待着CPU为它分配执行时间。
(3)等待(Wating):处于这种状态的线程不会被分配CPU执行时间。等待状态又分为无限期等待和有限期等待,处于无限期等待的线程需要被其他线程显示地唤醒,没有设置Timeout参数的Object.wait()、没有设置Timeout参数的Thread.join()方法都会使线程进入无限期等待状态;有限期等待状态无须等待被其他线程显示地唤醒,在一定时间之后它们会由系统自动唤醒,Thread.sleep()、设置了Timeout参数的Object.wait()、设置了Timeout参数的Thread.join()方法都会使线程进入有限期等待状态。
(4)阻塞(Blocked):线程被阻塞了,“阻塞状态”与”等待状态“的区别是:”阻塞状态“在等待着获取到一个排他锁,这个时间将在另外一个线程放弃这个锁的时候发生;而”等待状态“则是在等待一段时间或者唤醒动作的发生。在程序等待进入同步区域的时候,线程将进入这种状态。
(5)结束(Terminated):已终止线程的线程状态,线程已经结束执行。
3、创建线程的方式
①继承Thread类
1 public class WebDownloader { 2 //继承Thread类来创建线程 3 public static void main(String[] args) { 4 //设置线程名字 5 Thread.currentThread().setName("main thread"); 6 MyThread myThread = new MyThread(); 7 myThread.setName("子线程:"); 8 //开启线程 9 myThread.start(); 10 for(int i = 0;i<5;i++){ 11 System.out.println(Thread.currentThread().getName() + i); 12 } 13 } 14 } 15 16 class MyThread extends Thread{ 17 //重写run()方法 18 public void run(){ 19 for(int i = 0;i < 10; i++){ 20 System.out.println(Thread.currentThread().getName() + i); 21 } 22 } 23 }
②实现Runnable接口
1 public class Thread_test01 { 2 //实现Runnable接口 3 public static void main(String[] args) { 4 //设置线程名字 5 Thread.currentThread().setName("main thread:"); 6 Thread thread = new Thread(new MyRunnable()); 7 thread.setName("子线程:"); 8 //开启线程 9 thread.start(); 10 for (int i = 0; i < 5; i++) { 11 System.out.println(Thread.currentThread().getName() + i); 12 } 13 } 14 } 15 16 class MyRunnable implements Runnable { 17 18 @Override 19 public void run() { 20 for (int i = 0; i < 10; i++) { 21 System.out.println(Thread.currentThread().getName() + i); 22 } 23 } 24 }
③实现Callable接口
1 //实现Callable接口 2 public class Thread_test01 { 3 4 public static void main(String[] args) { 5 //执行Callable 方式,需要FutureTask 实现实现,用于接收运算结果 6 FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyCallable()); 7 new Thread(futureTask).start(); 8 //接收线程运算后的结果 9 try { 10 Integer sum = futureTask.get(); 11 System.out.println(sum); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } catch (ExecutionException e) { 15 e.printStackTrace(); 16 } 17 } 18 } 19 20 class MyCallable implements Callable<Integer> { 21 22 @Override 23 public Integer call() throws Exception { 24 int sum = 0; 25 for (int i = 0; i < 100; i++) { 26 sum += i; 27 } 28 return sum; 29 } 30 }
④线程池
1 package cn.Thread_demo; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 5 //线程池实现 6 public class Thread_test01 { 7 8 public static void main(String[] args) { 9 //创建线程池 10 ExecutorService executorService = Executors.newFixedThreadPool(10); 11 ThreadPool threadPool = new ThreadPool(); 12 for(int i =0;i<5;i++){ 13 //为线程池分配任务 14 executorService.submit(threadPool); 15 } 16 //关闭线程池 17 executorService.shutdown(); 18 } 19 } 20 21 class ThreadPool implements Runnable { 22 23 @Override 24 public void run() { 25 for(int i = 0 ;i<10;i++){ 26 System.out.println(Thread.currentThread().getName() + ":" + i); 27 } 28 } 29 }
4、线程终止
1 package cn.Thread_demo; 2 3 /** 4 * @Classname TerminateThread 5 * @Description TODO 6 * @Date 2019-5-10 17:08 7 * @Created by Administrator 8 * <p> 9 * 终止线程的方式 10 * 1、线程正常执行完毕----》次数 11 * 2、外部干涉----》加入标识 12 * 不使用stop destroy 13 */ 14 public class TerminateThread implements Runnable { 15 //1、加入标识,标记线程体是否可以运行 16 private boolean flag; 17 private String name; 18 19 public TerminateThread(String name) { 20 this.name = name; 21 } 22 23 24 @Override 25 public void run() { 26 int i = 0; 27 // 2、关联标识,ture--->运行 false--->停止 28 while (flag) { 29 System.out.println(name + "####----" + i++); 30 } 31 } 32 33 // 3、对外提供方法改变标识 34 public void terminateThread() { 35 this.flag = false; 36 } 37 38 public static void main(String[] args) { 39 TerminateThread tt = new TerminateThread("J罗"); 40 new Thread(tt).start(); 41 42 for (int i = 0; i < 44; i++) { 43 if (i==33){ 44 tt.terminateThread(); 45 System.out.println("Game,over"); 46 } 47 System.out.println("main---"+i); 48 } 49 } 50 }
运行结果图
5、守护线程
* 守护线程:是为用户线程服务的;jvm停止不用等待守护线程执行完毕
* 默认:用户线程。jvm等待用户线程执行完毕才会停止
1 package cn.Thread_demo; 2 3 /** 4 * @Classname DaemonTest 5 * @Description TODO 6 * @Date 2019-5-13 10:59 7 * @Created by Administrator 8 * <p> 9 * 守护线程:是为用户线程服务的;jvm停止不用等待守护线程执行完毕 10 * 默认:用户线程jvm等待用户线程执行完毕才会停止 11 */ 12 public class DaemonTest { 13 public static void main(String[] args) { 14 God god = new God(); 15 You you = new You(); 16 Thread t= new Thread(god); 17 t.setDaemon(true); //将用户线程调整为守护 18 t.start(); 19 new Thread(you).start(); 20 } 21 } 22 23 class You extends Thread { 24 public void run() { 25 for (int i = 0; i < 365 * 100; i++) { 26 System.out.println("happy life..."); 27 } 28 System.out.println("ene ene ene!"); 29 } 30 } 31 32 class God extends Thread { 33 public void run() { 34 for (; true; ) { 35 System.out.println("bless you..."); 36 } 37 } 38 }