文档目录:html
1、进程与线程java
2、多线程的实现安全
3、获取线程名与线程对象多线程
5、线程调度与优先级ide
6、线程安全(重点)this
7、死锁spa
---------------------------------------分割线:正文--------------------------------------------------------线程
一、基本概念
进程是一个应用程序。
线程是一个进程中的执行场景/执行单元。
一个进程能够启动多个线程
二、举例说明进程与线程、
java输出helloworld回车,先启动JVM是一个进行,JVM再启动一个主线程调用main方法,同时再启动一个垃圾回收线程负责看护,回收垃圾,至少两个线程并发。
三、进程与线程的关系
阿里巴巴:进程A
马云:阿里巴巴的一个线程
张小龙:阿里巴巴的一个线程
京东:进程B
强东:jd的一个线程
奶茶:jd的一个吸纳还曾
进程A与B内存独立不共享(阿里与jd资源不共享)
线程A与线程B:JAVA中堆内存与方法区内存共享,栈内存独立
四、多线程机制的目的
提升程序的处理效率
一、第一种实现方式:继承java.lang.Thread方法,并从新run方法
1 package JAVAADVANCE; 2 public class TestAdvance37TestThread01 { 3 //这里是main方法,这里的代码属于主线程,在主线程中运行
4 public static void main(String[] args) { 5 //新建一个分支线程对象,
6 MyThread myThread=new MyThread(); 7 //start开启新的栈空间,启动一个分支线程,启动成功线程自动调用run方法,而直接调用MyThread.run()不会启动多线程
8 myThread.start(); 9 //这里的代码运行在主线程中
10 for (int i=0;i<100;i++){ 11 System.out.println("主线程------->"+i); 12 } 13 } 14 } 15 class MyThread extends Thread{ 16 @Override 17 public void run() { 18 //编写程序,这段代码在分支线程中执行
19 for(int i=0;i<100;i++){ 20 System.out.println("分支线程------->"+i); 21 } 22 } 23 }
查看执行结果片断:主线程与分支线程是并发的
1 主线程------->91
2 主线程------->92
3 分支线程------->0
4 主线程------->93
5 分支线程------->1
6 主线程------->94
7 主线程------->95
二、第二种实现方式:编写一个类,实现java.lang.Runnable接口,实现run方法(建议使用,由于此类还能够继承其余方法)
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread02 { 4 public static void main(String[] args) { 5 //建立线程对象,将可运行的对象封装成线程对象
6 Thread t = new Thread(new MyRunnable()); 7 t.start(); 8 //这里的代码运行在主线程中
9 for (int i = 0; i < 100; i++) { 10 System.out.println("主线程------->" + i); 11 } 12 } 13 } 14 class MyRunnable implements Runnable{ 15 @Override 16 public void run() { 17 for(int i=0;i<100;i++){ 18 System.out.println("分支线程------->"+i); 19 } 20 } 21 }
查看执行结果片断:主线程与分支线程是并发的
1 分支线程------->54
2 主线程------->4
3 主线程------->5
4 分支线程------->55
5 主线程------->6
6 主线程------->7
三、第三种实现方式:采用匿名内部类方法
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread03 { 4 public static void main(String[] args) { 5 Thread t = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 for (int i = 0; i < 100; i++) { 9 System.out.println("分支线程------->" + i); 10 } 11 } 12 }); 13 //启动分支线程
14 t.start(); 15 for (int i = 0; i < 100; i++) { 16 System.out.println("主线程------->" + i); 17 } 18 } 19 }
查看执行结果片断:主线程与分支线程是并发的
1 分支线程------->10
2 主线程------->12
3 分支线程------->11
4 主线程------->13
5 分支线程------->12
6 主线程------->14
7 分支线程------->13
四、第四种实现方式:实现callable接口(JDK8新特性)
(1)优先与缺点:
优势:能够拿到线程的执行结果
缺点:效率比较低,获取结果时,当前线程受阻塞
(2)实现方式
1 package JAVAADVANCE; 2
3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.Future; 6 import java.util.concurrent.FutureTask; 7
8 public class TestAdvance37TestThread10 { 9 public static void main(String[] args) { 10 //建立一个将来任务对象,须要黑一个callable接口实现类的对象,这里使用匿名内部类
11 FutureTask task=new FutureTask(new Callable() { 12 @Override 13 public Object call() throws Exception { 14 //call()相似run方法,可是有返回值 15 //模拟行为
16 System.out.println("call method begin"); 17 Thread.sleep(1000*10); 18 System.out.println("call method end"); 19 int a=100; 20 int b=200; 21 return a+b; //自动装箱,300结果变为Integer
22 } 23 }); 24 //建立线程对象
25 Thread t=new Thread(task); 26 //启动线程
27 t.start(); 28 //获取t线程的返回结果
29 try { 30 Object obj=task.get(); 31 System.out.println("线程的执行结果为:"+obj); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } catch (ExecutionException e) { 35 e.printStackTrace(); 36 } 37 //main方法这里的程序要想执行必须等待get方法
38 System.out.println("hello world"); 39
40 } 41 }
查看执行结果:hello world在10秒后展现
call method begin call method end 线程的执行结果为:300 hello world
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread04 { 4 public static void main(String[] args) { 5 //获取当前线程对象
6 Thread t1=Thread.currentThread(); 7 System.out.println("main方法下的当前线程名:"+t1.getName()); 8 MyThread t2=new MyThread(); 9 //查看线程默认名
10 System.out.println("线程默认名:"+t2.getName()); 11 t2.setName("ttttt"); 12 System.out.println("修改后的线程名:"+t2.getName()); 13 } 14 }
查看执行结果
main方法下的当前线程名:main 线程默认名:Thread-0 修改后的线程名:ttttt
一、概念:
(1)sleep为静态方法
(2)参数为毫秒
(3)做用:让当前线程进入休眠,进入"阻塞状态",放弃占用cpu时间片,让给其余线程使用
二、举例说明sleep方法
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread05 { 4 public static void main(String[] args) { 5 //让当前进程进入休眠状态,睡眠5秒
6 try { 7 Thread.sleep(1000*5); 8 System.out.println("hello world"); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 } 13 }
5秒后控制台打印hello world
三、停止进程的睡眠
注:run()方法内只能try catch,不能throws,由于子类不能比父类抛出更多的异常
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread06 { 4 public static void main(String[] args) { 5 Thread t=new Thread(new MyRunnable2()); 6 t.setName("t"); 7 t.start(); 8 try { 9 Thread.sleep(1000*5); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 //终于线程的睡眠
14 t.interrupt(); 15 } 16 } 17
18 class MyRunnable2 implements Runnable{ 19 @Override 20 public void run() { 21 System.out.println(Thread.currentThread().getName()+"---->begin"); 22 try { 23 Thread.sleep(1000*60*60*24*365); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 System.out.println(Thread.currentThread().getName()+"----->end"); 28 } 29 }
查看运行结果:sleep5秒后出现异常信息,进程被停止
t---->begin java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at JAVAADVANCE.MyRunnable2.run(TestAdvance37TestThread06.java:23) at java.lang.Thread.run(Thread.java:748) t----->end Process finished with exit code 0
四、强行终止进程执行
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread07 { 4 public static void main(String[] args) { 5 Thread t=new Thread(new MyRunnable3()); 6 t.setName("t"); 7 t.start(); 8 try { 9 Thread.sleep(1000*5); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 t.stop(); 14 } 15 } 16
17 class MyRunnable3 implements Runnable{ 18 @Override 19 public void run() { 20 for(int i=0;i<10;i++){ 21 System.out.println(Thread.currentThread().getName()+"------>"+i); 22 try { 23 Thread.sleep(1000); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 } 29 }
stop方法的缺点:容易丢失数据,直接将线程杀死
五、合理的终止一个线程的执行
1 package JAVAADVANCE; 2
3 import static java.lang.Thread.sleep; 4
5 public class TestAdvance37TestThread08 { 6 public static void main(String[] args) { 7 MyRunnable4 r=new MyRunnable4(); 8 Thread t=new Thread(r); 9 t.setName("t"); 10 t.start(); 11 try { 12 sleep(1000*5); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 //何时停止t改成false
17 r.run=false; 18 } 19 } 20
21 class MyRunnable4 implements Runnable{ 22 //打一个布尔标记
23 boolean run=true; 24 @Override 25 public void run() { 26
27 for(int i=0;i<10;i++){ 28 if(run){ 29 System.out.println(Thread.currentThread().getName()+"----->"+i); 30 try { 31 sleep(1000); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 } 36
37 else { 38 //save保存代码 39 //终止当前线程
40 return; 41 } 42 } 43 } 44 }
查看执行结果,5秒后执行结果。
t----->0 t----->1 t----->2 t----->3 t----->4
一、分两种:抢占式调度模型与均分式调度模型,java属于前者
二、经常使用方法:
(1)设置线程的优先级:void setPrority()
(2)获取线程的优先级:int getPrority()
优先级分:1,5,10(最高)
(3)进程让位:static void yield()
(4)合并线程程:t.join() //当前线程阻塞,t线程加入当前线程中
6、线程安全(重点)
一、含义:
不出现异常,也不会出现错误,程序僵持,难以调试
二、举例:
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread09 { 4 public static void main(String[] args) { 5 Object o1=new Object(); 6 Object o2=new Object(); 7 Thread t1=new MyThread1(o1,o2); 8 Thread t2=new MyThread2(o1,o2); 9 t1.start(); 10 t2.start(); 11 } 12 } 13 class MyThread1 extends Thread{ 14 Object o1; 15 Object o2; 16 public MyThread1(Object o1,Object o2){ 17 this.o1=o1; 18 this.o2=o2; 19 } 20 public void run(){ 21 synchronized (o1){ 22 try { 23 Thread.sleep(1000); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 synchronized (o2){} 28 } 29 } 30 } 31 class MyThread2 extends Thread{ 32 Object o1; 33 Object o2; 34 public MyThread2(Object o1,Object o2){ 35 this.o1=o1; 36 this.o2=o2; 37 } 38 public void run(){ 39 synchronized (o2){ 40 try { 41 Thread.sleep(1000); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 synchronized (o1){} 46 } 47 } 48 }
程序运行一直不会结束也没有返回
三、解决方案:
程序编写使用时尽可能避免synchronized 方法嵌套使用