多线程入门总结
Posted caolyl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程入门总结相关的知识,希望对你有一定的参考价值。
要更好的理解多线程的话,必须要把多线程的生命周期搞懂。
多线程的生命周期
1.新建(New):线程创建以后就处于新建状态,Thread t = new Thread();
2.就绪(Runnable):当线程调用start()方法就进入就绪状态,线程进入就绪状态后不会立即执行,而是会等待CPU来调用。
3.运行(Running):当CPU调用就绪的线程就进入运行状态了。
4.阻塞(Blocked):处于运行状态的线程由于某种原因,暂时放弃对CPU的使用权,此时进入阻塞状态,直到其进入就绪状态线程才能重新调用进入到运行状态。
根据阻塞原因的不同,阻塞状态可分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态。
2.同步阻塞:线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5.死亡(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
线程的创建的常用两种方式
1.继承Thread类,重写该类的run()方法。
public class MyThread extends Thread { private String name; private static int num = 10000; public MyThread(String name) { this.name = name; } public void run() { for (int i = 1; i > 0; i++) { if(num>0){ num = num-1; }else{ break; } System.out.println("程序" + name + "在运行,当前num值"+num); } } public static void main(String[] args) { Thread thread1 = new MyThread("MyThread1");//新建线程MyThread,线程进入新建状态 Thread thread2 = new MyThread("MyThread2"); thread1.start();//线程调用start()进入就绪状态等待CPU调用 thread2.start(); } }
2.实现Runnable接口
public class MyRunnable implements Runnable { private String name; private static int num = 10000; public MyRunnable(String name) { this.name = name; } @Override public void run() { for (int i = 1; i > 0; i++) { if (num > 0) { num = num - 1; System.out.println("程序" + name + "在运行,当前num值" + num); } else { break; } } } public static void main(String[] args) { Runnable runnable1 = new MyRunnable("MyRunnable1"); Runnable runnable2 = new MyRunnable("MyRunnable2"); Thread thread1 = new Thread(runnable1); //新建线程MyRunnable1,线程进入新建状态 Thread thread2 = new Thread(runnable2); thread1.start(); //调用start方法,进入就绪状态 thread2.start(); } }
3.Thread和Runnable的区别
这里用最经典的买票举例
先贴代码吧
public class MyThread extends Thread { private int num = 5; private String name; public MyThread(String name) { this.name = name; } public void run() { try { for (int i = 1; i > 0; i++) { if (num > 0) { num--; } else { break; } sleep(100); System.out.println(name + "窗口,当前票数" + num); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { MyThread t1 = new MyThread("A"); MyThread t2 = new MyThread("B"); t1.start(); t2.start(); } }
用继承Thread方式运行结果可以看到车票被重复卖出了。再来看看实现Runnable接口的方式
public class MyRunnable implements Runnable { private int num = 5; @Override public void run() { for (int i = 1; i > 0; i++) { if (num > 0) { num--; System.out.println(Thread.currentThread().getName() + "窗口,当前票数" + num); } else { break; } } } public static void main(String[] args) { Runnable runnable = new MyRunnable(); new Thread(runnable, "A").start(); new Thread(runnable, "B").start(); } }
相信你已经可以看出区别了,但是多运行几次你会发现
这是因为线程执行会出现抢占资源的情况导致不能同步,所以要加上synchronized关键字。
总结
实现Runnable接口比继承Thread类所具有的优势:
(1):适合多个相同的程序代码的线程去处理同一个资源。
(2):可以避免java中的单继承的限制。
(3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
(4):你只要记住实际开发中一般都用实现Runnable的方式就完事了。
以上是关于多线程入门总结的主要内容,如果未能解决你的问题,请参考以下文章