一、理論概念
進程與線程
進程(PRocess)是計算機中的程序關于某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位。
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
二、線程的java實現
目前實現java線程有2種方式,繼承Thread類和實現Runnable接口,重寫run方法。
1、實現Runnable接口
實現 Runnable的接口的好處是實現變量的共享,多個線程使用同一個Runable對象,如上代碼塊中的成員變量j:
package src;/** * * @author Shawn Wang * */public class MyThread implements Runnable { private int j = 100; @Override public void run() { while (true) { if (j > 0) { System.out.println(Thread.currentThread().getName() + "-- num:" + j--); } else { break; } } } public static void main(String[] args) { MyThread mt = new MyThread(); Thread thread1 = new Thread(mt); Thread thread2 = new Thread(mt); Thread thread3 = new Thread(mt); thread1.start(); thread2.start(); thread3.start(); }}
輸出結果:
Thread-1-- num:100Thread-3-- num:98Thread-2-- num:99Thread-2-- num:95Thread-3-- num:96Thread-1-- num:97Thread-1-- num:92Thread-1-- num:91Thread-3-- num:93Thread-3-- num:89Thread-3-- num:88Thread-2-- num:94Thread-2-- num:86Thread-2-- num:85Thread-2-- num:84Thread-3-- num:87Thread-3-- num:82Thread-1-- num:90Thread-1-- num:80Thread-3-- num:81Thread-3-- num:78Thread-3-- num:77Thread-3-- num:76Thread-3-- num:75Thread-3-- num:74Thread-2-- num:83Thread-2-- num:72Thread-2-- num:71Thread-2-- num:70Thread-3-- num:73Thread-1-- num:79Thread-3-- num:68Thread-3-- num:66Thread-3-- num:65Thread-2-- num:69Thread-2-- num:63Thread-2-- num:62Thread-2-- num:61Thread-2-- num:60Thread-2-- num:59Thread-2-- num:58Thread-2-- num:57Thread-2-- num:56Thread-2-- num:55Thread-2-- num:54Thread-2-- num:53Thread-2-- num:52Thread-3-- num:64Thread-1-- num:67Thread-3-- num:50Thread-2-- num:51Thread-3-- num:48Thread-1-- num:49Thread-3-- num:46Thread-2-- num:47Thread-3-- num:44Thread-1-- num:45Thread-3-- num:42Thread-2-- num:43Thread-3-- num:40Thread-1-- num:41Thread-3-- num:38Thread-2-- num:39Thread-3-- num:36Thread-1-- num:37Thread-3-- num:34Thread-2-- num:35Thread-3-- num:32Thread-1-- num:33Thread-3-- num:30Thread-2-- num:31Thread-3-- num:28Thread-1-- num:29Thread-3-- num:26Thread-2-- num:27Thread-3-- num:24Thread-1-- num:25Thread-3-- num:22Thread-2-- num:23Thread-3-- num:20Thread-1-- num:21Thread-3-- num:18Thread-2-- num:19Thread-3-- num:16Thread-1-- num:17Thread-3-- num:14Thread-2-- num:15Thread-3-- num:12Thread-1-- num:13Thread-3-- num:10Thread-2-- num:11Thread-3-- num:8Thread-1-- num:9Thread-3-- num:6Thread-2-- num:7Thread-3-- num:4Thread-1-- num:5Thread-3-- num:2Thread-2-- num:3Thread-1-- num:1
2、繼承Thread類
package src;public class ThreadClient extends Thread { public ThreadClient(String name) { super(name); } @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i <= 10; i++) { System.out.println(currentThread().getName() + ":" + i); } } public static void main(String[] args) { ThreadClient thread1 = new ThreadClient("thread1"); ThreadClient thread2 = new ThreadClient("thread1"); ThreadClient thread3 = new ThreadClient("thread1"); thread1.start(); thread2.start(); thread3.start(); }}
輸出結果
thread1:0thread1:1thread1:0thread1:1thread1:0thread1:1thread1:2thread1:3thread1:4thread1:5thread1:6thread1:2thread1:2thread1:3thread1:4thread1:3thread1:4thread1:5thread1:6thread1:7thread1:7thread1:8thread1:9thread1:10thread1:5thread1:6thread1:7thread1:8thread1:9thread1:8thread1:9thread1:10thread1:10
疑問:
為什么要重寫 run方法?
run方法時存儲線程所要運行的代碼,不能在直接調用run方法,需要通過start方法來調用。
三、線程同步
場景:如果線程進行了sleep 操作時,其他線程對共享變量做了改變,會造成數據不同步問題。
package src;/** * * @author Shawn Wang * */public class MyThread implements Runnable { private int j = 100; @Override public void run() { while (true) { if (j > 0) { try { Thread.sleep(1000);// 當前線程休眠1秒 } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "-- num:" + j--); } else { break; } } } public static void main(String[] args) { MyThread mt = new MyThread(); Thread thread1 = new Thread(mt); Thread thread2 = new Thread(mt); Thread thread3 = new Thread(mt); thread1.start(); thread2.start(); thread3.start(); }}
輸出結果:
Thread-1-- num:100Thread-2-- num:99Thread-3-- num:98Thread-1-- num:97Thread-3-- num:95Thread-2-- num:96Thread-1-- num:94Thread-2-- num:92Thread-3-- num:93Thread-3-- num:91Thread-2-- num:90Thread-1-- num:90Thread-3-- num:89Thread-2-- num:88Thread-1-- num:87Thread-3-- num:86Thread-2-- num:85Thread-1-- num:85Thread-3-- num:84Thread-2-- num:83Thread-1-- num:82Thread-3-- num:81Thread-1-- num:80Thread-2-- num:80Thread-3-- num:79Thread-2-- num:77Thread-1-- num:78Thread-3-- num:76Thread-2-- num:75Thread-1-- num:74Thread-2-- num:73Thread-3-- num:71Thread-1-- num:72Thread-2-- num:70Thread-1-- num:69Thread-3-- num:69Thread-2-- num:68Thread-3-- num:66Thread-1-- num:67Thread-2-- num:65Thread-1-- num:64Thread-3-- num:64Thread-2-- num:63Thread-1-- num:62Thread-3-- num:61Thread-2-- num:60Thread-3-- num:58Thread-1-- num:59Thread-2-- num:57Thread-1-- num:56Thread-3-- num:56Thread-2-- num:55Thread-1-- num:54Thread-3-- num:54Thread-2-- num:53Thread-3-- num:52Thread-1-- num:52Thread-3-- num:51Thread-2-- num:50Thread-1-- num:51Thread-3-- num:49Thread-1-- num:48Thread-2-- num:48Thread-3-- num:47Thread-1-- num:46Thread-2-- num:45Thread-1-- num:44Thread-2-- num:42Thread-3-- num:43Thread-3-- num:40Thread-1-- num:39Thread-2-- num:41Thread-2-- num:38Thread-3-- num:37Thread-1-- num:38Thread-1-- num:36Thread-2-- num:35Thread-3-- num:36Thread-1-- num:34Thread-2-- num:33Thread-3-- num:33Thread-1-- num:32Thread-3-- num:30Thread-2-- num:31Thread-1-- num:29Thread-3-- num:29Thread-2-- num:29Thread-3-- num:28Thread-1-- num:28Thread-2-- num:28Thread-1-- num:27Thread-2-- num:26Thread-3-- num:27Thread-1-- num:25Thread-2-- num:24Thread-3-- num:24Thread-1-- num:23Thread-3-- num:22Thread-2-- num:22Thread-1-- num:21Thread-3-- num:20Thread-2-- num:20Thread-1-- num:19Thread-3-- num:18Thread-2-- num:17Thread-3-- num:16Thread-1-- num:15Thread-2-- num:14Thread-2-- num:13Thread-3-- num:12Thread-1-- num:13Thread-2-- num:11Thread-1-- num:10Thread-3-- num:10Thread-2-- num:9Thread-1-- num:7Thread-3-- num:8Thread-2-- num:6Thread-3-- num:5Thread-1-- num:5Thread-2-- num:4Thread-3-- num:3Thread-1-- num:2Thread-2-- num:1Thread-1-- num:0Thread-3-- num:-1
出現了負數。
解決加上同步鎖synchronized
同步代碼塊的格式:
synchronized(對象){
需要被同步的代碼;
}
package src;/** * * @author Shawn Wang * */public class MyThread implements Runnable { private int j = 100; @Override public void run() { while (true) { synchronized (this) { if (j > 0) { try { Thread.sleep(1000);// 當前線程休眠1秒 } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "-- num:" + j--); } else { break; } } } } public static void main(String[] args) { MyThread mt = new MyThread(); Thread thread1 = new Thread(mt); Thread thread2 = new Thread(mt); Thread thread3 = new Thread(mt); thread1.start(); thread2.start(); thread3.start(); }}
新聞熱點
疑難解答