程序运行时,其实是CPU在执行程序的进程,为了提高工作效率一个进程可以有多个线程。
Java的多线程:
其实我们之前就见过Java的线程,main就是Java的一个线程,还有另一个条线程总是和main同时运行,那就是垃圾回收线程。
Java的线程有四种状态:
1,被创建:new Thread
2,运行(就绪):JVM调用Thread的start方法执行Thread的run中的内容
3,冻结:sleep(毫秒),wait()-notify()
4,消亡
Java可以通过继承Thread类和实现Runnable接口实现多线程技术。
通过继承Thread类实现多线程:
方法:
1,创建自定义的类继承Thread类
2,覆盖Thread类中的run方法
3,建立自定义的线程类的子类对象,即创建线程对象
4,调用start方法让JVM启动自定义线程(其实就是告诉JVM去运行自定义的run方法中的内容)
class DefinedThread extends Thread//自定义线程类继承Thread类 { ... public void run() { ...//复写Thread类中的run方法,定义该线程执行的内容 } ... } class MultThread { public static void main(String[] args)//main就是一个线程 { DefinedThread dt = new DefinedThread();//创建线程对象 dt.start();//启动线程 } }
通过实现Runnable接口实现多线程:
1,创建自定义的类实现Runnable接口
2,覆盖接口中的run方法
3,通过Thread类创建线程对象,并将自定义类的对象作为参数传递给Thread类的构造器
4,Thread类对象调用start方法开启线程
class DefinedThread implements Runnable//自定义类实现Runnable接口 { ... public void run() { ...//复写接口的run方法,定义该线程执行的内容 } ... } class MultThread { public static void main(String[] args)//main就是一个线程 { DefinedThread dt = new DefinedThread(); Thread t = new Thread(dt);//把自定义类的子类对象当作参数传递给Thread构造器 t.start();//线程对象t调用start方法开启线程 } }
Thread和Runnable之间的关系:
1,一个类只能继承一个类,而可以实现多个接口,就这点而言Thread有局限性,Runnable扩展性好
2,Thread对象调用Thread(Runnable run)或者Thread(Runnable run, String name)构造方法创建线程,使用的是同一个Runnable实例对象内的资源,就这点而言,Runnable适合资源共享。(当然继承Thread类,使用static变量也能共享资源,但这样比较麻烦而且static的生命周期长)
3,通过Thread类的定义 public class Thread extends Object implements Runnable ,可以看出Thread类其实也实现了Runnable接口,不过Thread中有start方法,而Runnable中没有,所以实现了Runnable的对象的run中的内容想要让JVM调用就必须把该对象传递给Thread的,由Thread的对象调用start方法启动线程从而运行run中的内容。
小例子:假如有4个窗口售票,票从1号到100号,我们先看继承Thread的MyThread类实现
1 class MultThread 2 { 3 public static void main(String[] args) 4 { 5 6 Thread t1 = new MyThread("窗口1"); 7 Thread t2 = new MyThread("窗口2"); 8 Thread t3 = new MyThread("窗口3"); 9 Thread t4 = new MyThread("窗口4"); 10 11 t1.start(); 12 t2.start(); 13 t3.start(); 14 t4.start(); 15 16 } 17 } 18 19 class MyThread extends Thread 20 { 21 private static int tick = 1; 22 MyThread(String name) 23 { 24 super(name); 25 } 26 public void run() 27 { 28 while(tick<=100) 29 { 30 System.out.println(this.getName()+"售出"+tick+"号票"); 31 tick++; 32 } 33 } 34 }通过实现了Runnable接口的MyR类
1 class MultThread 2 { 3 public static void main(String[] args) 4 { 5 MyR r = new MyR(); 6 Thread t1 = new Thread(r,"窗口1"); 7 Thread t2 = new Thread(r,"窗口2"); 8 Thread t3 = new Thread(r,"窗口3"); 9 Thread t4 = new Thread(r,"窗口4"); 10 11 t1.start(); 12 t2.start(); 13 t3.start(); 14 t4.start(); 15 16 } 17 } 18 19 class MyR implements Runnable 20 { 21 private int tick = 1; 22 public void run() 23 { 24 while(tick<=100) 25 { 26 System.out.println(Thread.currentThread().getName()+"售出"+tick+"号票"); 27 tick++; 28 } 29 } 30 }但是对于双核或者多核的CPU来说这样会带来程序的风险,比如有可能出现1号票被卖了2次的情况,所以为了线程的安全性引出了同步的概念,这个笔记记录在下一节。