在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。
对于直接继承Thread的类来说,代码大致框架是:
class 类名 extends Thread{ 方法1; 方法2; … public void run(){ // other code… } 属性1; 属性2; … }
先看一个简单的例子:
/** * @author Hashsound 继承Thread类,直接调用run方法 * */ class hello extends Thread { private String name; public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i < 5; i++) { System.out.println(name + "运行 " + i); } } public static void main(String[] args) { hello h1 = new hello("A"); hello h2 = new hello("B"); h1.run(); h2.run(); } }【运行结果】:
public static void main(String[] args) { hello h1=new hello("A"); hello h2=new hello("B"); h1.start(); h2.start(); }然后运行程序,输出的可能的结果如下:
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } private native void start0();
注意我用红色加粗的那一条语句,说明此处调用的是start0()。并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。
但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。
通过实现Runnable接口:
大致框架是:
来先看一个小例子吧:
class 类名 implements Runnable{ 方法1; 方法2; … public void run(){ // other code… } 属性1; 属性2; … }
/** * @author Hashsound 实现Runnable接口 * */ class hello implements Runnable { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i < 5; i++) { System.out.println(name + "运行 " + i); } } public static void main(String[] args) { hello h1=new hello("线程A"); Thread demo= new Thread(h1); hello h2=new hello("线程B"); Thread demo1=new Thread(h2); demo.start(); demo1.start(); } private String name; }【可能的运行结果】:
class Thread implements Runnable { //… public void run() { if (target != null) { target.run(); } } }
/** * @author Rollen-Holt 继承Thread类,不能资源共享 * */ class hello extends Thread { public void run() { for (int i = 0; i < 7; i++) { if (count > 0) { System.out.println("count= " + count--); } } } public static void main(String[] args) { hello h1 = new hello(); hello h2 = new hello(); hello h3 = new hello(); h1.start(); h2.start(); h3.start(); } private int count = 5; }【运行结果】:
大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。
我们换为Runnable接口
class MyThread implements Runnable{ private int ticket = 5; //5张票 public void run() { for (int i=0; i<=20; i++) { if (this.ticket > 0) { System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--); } } } } public class lzwCode { public static void main(String [] args) { MyThread my = new MyThread(); new Thread(my, "1号窗口").start(); new Thread(my, "2号窗口").start(); new Thread(my, "3号窗口").start(); } }【运行结果】:
总结一下吧:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
所以,本人建议大家尽量实现接口。
/** * @author Hashsound * 取得线程的名称 * */ class hello implements Runnable { public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args) { hello he = new hello(); new Thread(he,"A").start(); new Thread(he,"B").start(); new Thread(he).start(); } }【运行结果】:
判断线程是否启动
/** * @author Hashsound 判断线程是否启动 * */ class hello implements Runnable { public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args) { hello he = new hello(); Thread demo = new Thread(he); System.out.println("线程启动之前---》" + demo.isAlive()); demo.start(); System.out.println("线程启动之后---》" + demo.isAlive()); } }【运行结果】
线程的强制执行:
/** * @author Hashsound 线程的强制执行 * */ class hello implements Runnable { public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args) { hello he = new hello(); Thread demo = new Thread(he,"线程"); demo.start(); for(int i=0;i<50;++i){ if(i>10){ try{ demo.join(); //强制执行demo }catch (Exception e) { e.printStackTrace(); } } System.out.println("main 线程执行-->"+i); } } }【运行的结果】:
/** * @author Hashsound 线程的休眠 * */ class hello implements Runnable { public void run() { for (int i = 0; i < 3; i++) { try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + i); } } public static void main(String[] args) { hello he = new hello(); Thread demo = new Thread(he, "线程"); demo.start(); } }【运行结果】:(结果每隔2s输出一个)
/** * @author Hashsound 线程的中断 * */ class hello implements Runnable { public void run() { System.out.println("执行run方法"); try { Thread.sleep(10000); System.out.println("线程完成休眠"); } catch (Exception e) { System.out.println("休眠被打断"); return; //返回到程序的调用处 } System.out.println("线程正常终止"); } public static void main(String[] args) { hello he = new hello(); Thread demo = new Thread(he, "线程"); demo.start(); try{ Thread.sleep(2000); }catch (Exception e) { e.printStackTrace(); } demo.interrupt(); //2s后中断线程 } }【运行结果】:
/** * @author Hashsound 后台线程 * */ class hello implements Runnable { public void run() { while (true) { System.out.println(Thread.currentThread().getName() + "在运行"); } } public static void main(String[] args) { hello he = new hello(); Thread demo = new Thread(he, "线程"); demo.setDaemon(true); demo.start(); } }
/** * @author Hashsound 线程的优先级 * */ class hello implements Runnable { public void run() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+"运行"+i); } } public static void main(String[] args) { Thread h1=new Thread(new hello(),"A"); Thread h2=new Thread(new hello(),"B"); Thread h3=new Thread(new hello(),"C"); h1.setPriority(8); h2.setPriority(2); h3.setPriority(6); h1.start(); h2.start(); h3.start(); } }【运行结果】:
/** * @author Hashsound 线程的优先级 * */ class hello implements Runnable { public void run() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+"运行"+i); if(i==3){ System.out.println("线程的礼让"); Thread.currentThread().yield(); } } } public static void main(String[] args) { Thread h1=new Thread(new hello(),"A"); Thread h2=new Thread(new hello(),"B"); h1.start(); h2.start(); } }
同步和死锁:
【问题引出】:比如说对于买票系统,有下面的代码:
/** * @author Hashsound * */ class hello implements Runnable { public void run() { for(int i=0;i<10;++i){ if(count>0){ try{ Thread.sleep(1000); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(count--); } } } public static void main(String[] args) { hello he=new hello(); Thread h1=new Thread(he); Thread h2=new Thread(he); Thread h3=new Thread(he); h1.start(); h2.start(); h3.start(); } private int count=5; }【运行结果】:
这里出现了-1,显然这个是错的。,应该票数不能为负值。
如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,
其他的线程必须等到这个线程结束之后才能继续执行。
【使用线程同步解决问题】
采用同步的话,可以使用同步代码块和同步方法两种来完成。
【同步代码块】:
语法格式:
synchronized(同步对象){ //需要同步的代码 }但是一般都把当前对象this作为同步对象。
/** * @author Hashsound * */ class hello implements Runnable { public void run() { for(int i=0;i<10;++i){ synchronized (this) { if(count>0){ try{ Thread.sleep(1000); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(count--); } } } } public static void main(String[] args) { hello he=new hello(); Thread h1=new Thread(he); Thread h2=new Thread(he); Thread h3=new Thread(he); h1.start(); h2.start(); h3.start(); } private int count=5; }【运行结果】:(每一秒输出一个结果)
/** * @author Hashsound * */ class hello implements Runnable { public void run() { for (int i = 0; i < 10; ++i) { sale(); } } public synchronized void sale() { if (count > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count--); } } public static void main(String[] args) { hello he = new hello(); Thread h1 = new Thread(he); Thread h2 = new Thread(he); Thread h3 = new Thread(he); h1.start(); h2.start(); h3.start(); } private int count = 5; }【运行结果】(每秒输出一个)
class Info { public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private String name = "Rollen"; private int age = 20; } /** * 生产者 * */ class Producer implements Runnable{ private Info info=null; Producer(Info info){ this.info=info; } public void run(){ boolean flag=false; for(int i=0;i<25;++i){ if(flag){ this.info.setName("Rollen"); try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } this.info.setAge(20); flag=false; }else{ this.info.setName("chunGe"); try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } this.info.setAge(100); flag=true; } } } } /** * 消费者类 * */ class Consumer implements Runnable{ private Info info=null; public Consumer(Info info){ this.info=info; } public void run(){ for(int i=0;i<25;++i){ try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } System.out.println(this.info.getName()+"<---->"+this.info.getAge()); } } } /** * 测试类 * */ class hello{ public static void main(String[] args) { Info info=new Info(); Producer pro=new Producer(info); Consumer con=new Consumer(info); new Thread(pro).start(); new Thread(con).start(); } }【运行结果】:
class Info { public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public synchronized void set(String name, int age){ this.name=name; try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } this.age=age; } public synchronized void get(){ try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } System.out.println(this.getName()+"<===>"+this.getAge()); } private String name = "Rollen"; private int age = 20; } /** * 生产者 * */ class Producer implements Runnable { private Info info = null; Producer(Info info) { this.info = info; } public void run() { boolean flag = false; for (int i = 0; i < 25; ++i) { if (flag) { this.info.set("Rollen", 20); flag = false; } else { this.info.set("ChunGe", 100); flag = true; } } } } /** * 消费者类 * */ class Consumer implements Runnable { private Info info = null; public Consumer(Info info) { this.info = info; } public void run() { for (int i = 0; i < 25; ++i) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } this.info.get(); } } } /** * 测试类 * */ class hello { public static void main(String[] args) { Info info = new Info(); Producer pro = new Producer(info); Consumer con = new Consumer(info); new Thread(pro).start(); new Thread(con).start(); } }【运行结果】:
class Info { public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public synchronized void set(String name, int age){ if(!flag){ try{ super.wait(); }catch (Exception e) { e.printStackTrace(); } } this.name=name; try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } this.age=age; flag=false; super.notify(); } public synchronized void get(){ if(flag){ try{ super.wait(); }catch (Exception e) { e.printStackTrace(); } } try{ Thread.sleep(100); }catch (Exception e) { e.printStackTrace(); } System.out.println(this.getName()+"<===>"+this.getAge()); flag=true; super.notify(); } private String name = "Rollen"; private int age = 20; private boolean flag=false; } /** * 生产者 * */ class Producer implements Runnable { private Info info = null; Producer(Info info) { this.info = info; } public void run() { boolean flag = false; for (int i = 0; i < 25; ++i) { if (flag) { this.info.set("Rollen", 20); flag = false; } else { this.info.set("ChunGe", 100); flag = true; } } } } /** * 消费者类 * */ class Consumer implements Runnable { private Info info = null; public Consumer(Info info) { this.info = info; } public void run() { for (int i = 0; i < 25; ++i) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } this.info.get(); } } } /** * 测试类 * */ class hello { public static void main(String[] args) { Info info = new Info(); Producer pro = new Producer(info); Consumer con = new Consumer(info); new Thread(pro).start(); new Thread(con).start(); } }【程序运行结果】: