Java多线程详解
线程(Thread)是指程序的运行流程,多线程机制指同时运行多个程序块。
Java中实现多线程有两种方法:继承Thread类;实现Runnable接口。
Thread类的run()方法的制定者:接口Runnable中的run();
在Thread类中没有完全实现Runnable接口中的run()方法。
Thread类是Runnable接口的子类,Thread类中的run()方法调用的是Runnable接口中的run()方法。
接口是由全局变量和公共抽象方法所组成的。
所以,在Thread子类中,必须覆写Thread类中的run()方法。
启动线程时,不能直接调用run()方法,而是调用从Thread类中继承而来的start()方法;
即同一个对象只能调用一次start方法。
如果一个类继承了Thread类,那么只能调用一次start()方法,如果多次调用,
将会出现“IllegalThreadStateException”异常。
Runnable接口中只有一个方法:run();
Runnable、Thread中的run方法和自定义的run方法之间的关系:
1 interface Runnable{ 2 public abstract void run(); 3 } //remove method body 4 5 public class Thread implements Runnable { 6 private Runnable target; //封装 7 public Thread(Runnable target,String name){ //构造函数,name是线程的名称 8 init(target); 9 } 10 11 private void init(Runnable target2) { //检验关口,给属性赋值 12 this.target = target; 13 } 14 15 public void run() { 16 if(target != null){ 17 target.run(); //此run方法指的是自定义的run方法,即Runable中的run方法 18 //整个过程中,只有一个对象,只有这个对象有能力调用自定 19 //义的run方法。 20 } 21 } 22 } 23 class MyThread implements Runnable{ 24 public void run() { //自定义的run方法 25 26 } 27 }
由于使用Runable的整个过程中,只产生一个对象,所以可以方便地实现资源的共享。
这也是Runable优于Thread之处。
Java程序每次运行至少启动两个线程:main线程、垃圾收集线程。
Thread类中常用的方法:
currentThread(静态),通过类名Thread直接调用;
判断线程是否启动(存活)
1 class MyThread implements Runnable{ 2 public void run(){ 3 for(int i=0;i<3;i++){ 4 System.out.println(Thread.currentThread().getName()+"运行………"+i); 5 } 6 } 7 } 8 9 public class ThreadAliveDemo { 10 11 public static void main(String[] args) { 12 MyThread mt = new MyThread(); 13 Thread t = new Thread(mt); 14 System.out.println("线程开始执行之前……"+t.isAlive()); 15 16 t.start(); 17 18 for(int i=0;i<5;i++){ 19 System.out.println("等待……"+i);//i值的不同,最后运行结果不同 20 } 21 22 System.out.println("线程开始执行之后……"+t.isAlive()); 23 for(int i=0;i<3;i++){ 24 System.out.println("main运行……"+i); 25 } 26 System.out.println("代码执行之后……"+t.isAlive()); 27 } 28 }
主线程有可能比其他线程先执行完,其他线程不会受到任何影响,不会随着主线程的结束而结束。
线程的强制执行
class MyThread implements Runnable{ public void run(){ for(int i=0;i<20;i++){ System.out.println(Thread.currentThread().getName()+"运行……"+i); } } } public class ThreadJoinDemo { public static void main(String[] args) { MyThread mt = new MyThread(); Thread t = new Thread(mt); t.start(); for(int i=0;i<30;i++){ if(i>10){ try{ t.join(); }catch(Exception e){} } System.out.println("Main线程"+i); } } }
线程的休眠:
sleep为静态方法,使用类名Thread直接调用
1 class MyThread implements Runnable{ 2 public void run(){ 3 for(int i=0;i<5;i++){ 4 try{ 5 Thread.sleep(1000);//每次输出都会间隔1000ms,达到延迟操作的结果 6 }catch(Exception e){} 7 System.out.println(Thread.currentThread().getName()+"…………"+i); 8 } 9 } 10 } 11 12 public class ThreadSleepDemo { 13 14 public static void main(String[] args) { 15 MyThread mt = new MyThread(); 16 new Thread(mt,"线程").start(); 17 } 18 19 }
线程的中断:
1 class MyThread implements Runnable{ 2 public void run(){ 3 System.out.println("进入run方法"); 4 try{ 5 Thread.sleep(10000); 6 System.out.println("已完成休眠"); 7 }catch(Exception e){ 8 System.out.println("休眠被终止"); 9 return; 10 } 11 System.out.println("正常结束"); 12 } 13 } 14 15 public class ThreadInterruptDemo { 16 public static void main(String[] args) { 17 MyThread mt = new MyThread(); 18 Thread t = new Thread(mt); 19 t.start(); 20 try{ 21 Thread.sleep(2000); 22 }catch(Exception e){} 23 t.interrupt(); 24 } 25 }
在使用join和sleep时,要进行异常处理。
线程的礼让:
1 class MyThread implements Runnable{ 2 public void run(){ 3 for(int i=0;i<5;i++){ 4 System.out.println(Thread.currentThread().getName()+"运行"+i); 5 if(i==2){ 6 System.out.print("线程礼让:"); 7 Thread.currentThread().yield(); 8 } 9 } 10 } 11 } 12 13 public class ThreadYieldDemo { 14 15 public static void main(String[] args) { 16 MyThread mt = new MyThread(); 17 Thread t1 = new Thread(mt,"线程A"); 18 Thread t2 = new Thread(mt,"线程B"); 19 t1.start(); 20 t2.start(); 21 } 22 }
每当线程满足条件(i=2)时,本线程就会停止,而让其他线程先执行。
同步:指多个操作在同一时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续进行。
解决资源共享的同步操作,可以使用同步代码块和同步方法两种方式完成。
同步代码块:
1 class MyThread implements Runnable{ 2 private int ticket = 20; 3 public void run(){ 4 for(int i=0;i<100;i++){ 5 synchronized(this){ //将当前对象(this)设置成同步对象 6 if(ticket>0){ 7 System.out.println(ticket--); 8 } 9 } 10 } 11 } 12 } 13 14 public class SynchronizedDemo { 15 16 public static void main(String[] args) { 17 MyThread mt = new MyThread(); 18 new Thread(mt).start(); 19 new Thread(mt).start(); 20 new Thread(mt).start(); 21 } 22 }
同步方法:(使用synchronized关键字将一个方法声明为同步方法)
1 class MyThread implements Runnable{ 2 private int ticket = 50; 3 public void run(){ 4 for(int i=0;i<100;i++){ 5 this.sale(); 6 } 7 } 8 private synchronized void sale() { 9 if(ticket>0){ 10 System.out.println(ticket--); 11 } 12 } 13 } 14 15 public class SynchronizedDemo { 16 17 public static void main(String[] args) { 18 MyThread mt = new MyThread(); 19 new Thread(mt).start(); 20 new Thread(mt).start(); 21 new Thread(mt).start(); 22 } 23 }
Java中方法定义的完整格式:
访问权限(public、default、protected、private)[final][static][synchronized]
返回值类型 void 方法名称(参数类型,参数名称)[throws Exception1,Exception2]
{
return 返回值;
}
死锁:指两个线程都在等着彼此先完成,造成了程序的停滞。
卖票:同一个动作处理同一资源
生产者消费者:不同动作处理同一资源
1 class Info{ 2 private String name = "zhangsan"; 3 private String content = "java"; 4 private boolean flag = false; 5 public synchronized void set(String name,String content){ 6 if(!flag){ 7 try{ 8 super.wait(); 9 }catch(InterruptedException e){ 10 e.printStackTrace(); 11 } 12 } 13 this.name = name; 14 this.content = content; 15 flag = false; 16 super.notify(); 17 } 18 public synchronized void get(){ 19 if(flag){ 20 try{ 21 super.wait(); 22 }catch(InterruptedException e){ 23 e.printStackTrace(); 24 } 25 } 26 System.out.println(name+ ":" +content); 27 flag = true; 28 super.notify(); 29 } 30 } 31 32 class Producer implements Runnable{ 33 private Info info = null; 34 public Producer(Info info){ 35 this.info = info; 36 } 37 public void run(){ 38 boolean flag = false; 39 for(int i=0;i<10;i++){ 40 if(flag){ 41 this.info.set("zhangsan", "java"); 42 flag = false; 43 }else{ 44 this.info.set("wangzhi","www"); 45 flag = true; 46 } 47 } 48 } 49 } 50 51 class Consumer implements Runnable{ 52 private Info info = null; 53 public Consumer(Info info){ 54 this.info = info; 55 } 56 public void run(){ 57 for(int i=0;i<10;i++){ 58 try{ 59 Thread.sleep(100); 60 }catch(Exception e){ 61 e.printStackTrace(); 62 } 63 this.info.get(); 64 } 65 } 66 } 67 68 public class ThreadCaseDemo { 69 70 public static void main(String[] args) { 71 Info i = new Info(); 72 Producer pro = new Producer(i); 73 Consumer con = new Consumer(i); 74 new Thread(pro).start(); 75 new Thread(con).start(); 76 } 77 }
停止线程运行:在多线程开发中可以通过设置标志位的方式停止一个线程的运行。