1、理論概念java
進程與線程多線程
進程(Process)是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位。併發
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程本身基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),可是它可與同屬一個進程的其餘的線程共享進程所擁有的所有資源.ide
進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。this
2、線程的Java實現spa
目前實現java線程有2種方式,繼承Thread類和實現Runnable接口,重寫run方法。線程
一、實現Runnable接口3d
實現 Runnable的接口的好處是實現變量的共享,多個線程使用同一個Runable對象,如上代碼塊中的成員變量j:code
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:100 Thread-3-- num:98 Thread-2-- num:99 Thread-2-- num:95 Thread-3-- num:96 Thread-1-- num:97 Thread-1-- num:92 Thread-1-- num:91 Thread-3-- num:93 Thread-3-- num:89 Thread-3-- num:88 Thread-2-- num:94 Thread-2-- num:86 Thread-2-- num:85 Thread-2-- num:84 Thread-3-- num:87 Thread-3-- num:82 Thread-1-- num:90 Thread-1-- num:80 Thread-3-- num:81 Thread-3-- num:78 Thread-3-- num:77 Thread-3-- num:76 Thread-3-- num:75 Thread-3-- num:74 Thread-2-- num:83 Thread-2-- num:72 Thread-2-- num:71 Thread-2-- num:70 Thread-3-- num:73 Thread-1-- num:79 Thread-3-- num:68 Thread-3-- num:66 Thread-3-- num:65 Thread-2-- num:69 Thread-2-- num:63 Thread-2-- num:62 Thread-2-- num:61 Thread-2-- num:60 Thread-2-- num:59 Thread-2-- num:58 Thread-2-- num:57 Thread-2-- num:56 Thread-2-- num:55 Thread-2-- num:54 Thread-2-- num:53 Thread-2-- num:52 Thread-3-- num:64 Thread-1-- num:67 Thread-3-- num:50 Thread-2-- num:51 Thread-3-- num:48 Thread-1-- num:49 Thread-3-- num:46 Thread-2-- num:47 Thread-3-- num:44 Thread-1-- num:45 Thread-3-- num:42 Thread-2-- num:43 Thread-3-- num:40 Thread-1-- num:41 Thread-3-- num:38 Thread-2-- num:39 Thread-3-- num:36 Thread-1-- num:37 Thread-3-- num:34 Thread-2-- num:35 Thread-3-- num:32 Thread-1-- num:33 Thread-3-- num:30 Thread-2-- num:31 Thread-3-- num:28 Thread-1-- num:29 Thread-3-- num:26 Thread-2-- num:27 Thread-3-- num:24 Thread-1-- num:25 Thread-3-- num:22 Thread-2-- num:23 Thread-3-- num:20 Thread-1-- num:21 Thread-3-- num:18 Thread-2-- num:19 Thread-3-- num:16 Thread-1-- num:17 Thread-3-- num:14 Thread-2-- num:15 Thread-3-- num:12 Thread-1-- num:13 Thread-3-- num:10 Thread-2-- num:11 Thread-3-- num:8 Thread-1-- num:9 Thread-3-- num:6 Thread-2-- num:7 Thread-3-- num:4 Thread-1-- num:5 Thread-3-- num:2 Thread-2-- num:3 Thread-1-- num:1
二、繼承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:0 thread1:1 thread1:0 thread1:1 thread1:0 thread1:1 thread1:2 thread1:3 thread1:4 thread1:5 thread1:6 thread1:2 thread1:2 thread1:3 thread1:4 thread1:3 thread1:4 thread1:5 thread1:6 thread1:7 thread1:7 thread1:8 thread1:9 thread1:10 thread1:5 thread1:6 thread1:7 thread1:8 thread1:9 thread1:8 thread1:9 thread1:10 thread1:10
疑問:
爲何要重寫 run方法?
run方法時存儲線程所要運行的代碼,不能在直接調用run方法,須要經過start方法來調用。
3、線程同步
場景:若是線程進行了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:100 Thread-2-- num:99 Thread-3-- num:98 Thread-1-- num:97 Thread-3-- num:95 Thread-2-- num:96 Thread-1-- num:94 Thread-2-- num:92 Thread-3-- num:93 Thread-3-- num:91 Thread-2-- num:90 Thread-1-- num:90 Thread-3-- num:89 Thread-2-- num:88 Thread-1-- num:87 Thread-3-- num:86 Thread-2-- num:85 Thread-1-- num:85 Thread-3-- num:84 Thread-2-- num:83 Thread-1-- num:82 Thread-3-- num:81 Thread-1-- num:80 Thread-2-- num:80 Thread-3-- num:79 Thread-2-- num:77 Thread-1-- num:78 Thread-3-- num:76 Thread-2-- num:75 Thread-1-- num:74 Thread-2-- num:73 Thread-3-- num:71 Thread-1-- num:72 Thread-2-- num:70 Thread-1-- num:69 Thread-3-- num:69 Thread-2-- num:68 Thread-3-- num:66 Thread-1-- num:67 Thread-2-- num:65 Thread-1-- num:64 Thread-3-- num:64 Thread-2-- num:63 Thread-1-- num:62 Thread-3-- num:61 Thread-2-- num:60 Thread-3-- num:58 Thread-1-- num:59 Thread-2-- num:57 Thread-1-- num:56 Thread-3-- num:56 Thread-2-- num:55 Thread-1-- num:54 Thread-3-- num:54 Thread-2-- num:53 Thread-3-- num:52 Thread-1-- num:52 Thread-3-- num:51 Thread-2-- num:50 Thread-1-- num:51 Thread-3-- num:49 Thread-1-- num:48 Thread-2-- num:48 Thread-3-- num:47 Thread-1-- num:46 Thread-2-- num:45 Thread-1-- num:44 Thread-2-- num:42 Thread-3-- num:43 Thread-3-- num:40 Thread-1-- num:39 Thread-2-- num:41 Thread-2-- num:38 Thread-3-- num:37 Thread-1-- num:38 Thread-1-- num:36 Thread-2-- num:35 Thread-3-- num:36 Thread-1-- num:34 Thread-2-- num:33 Thread-3-- num:33 Thread-1-- num:32 Thread-3-- num:30 Thread-2-- num:31 Thread-1-- num:29 Thread-3-- num:29 Thread-2-- num:29 Thread-3-- num:28 Thread-1-- num:28 Thread-2-- num:28 Thread-1-- num:27 Thread-2-- num:26 Thread-3-- num:27 Thread-1-- num:25 Thread-2-- num:24 Thread-3-- num:24 Thread-1-- num:23 Thread-3-- num:22 Thread-2-- num:22 Thread-1-- num:21 Thread-3-- num:20 Thread-2-- num:20 Thread-1-- num:19 Thread-3-- num:18 Thread-2-- num:17 Thread-3-- num:16 Thread-1-- num:15 Thread-2-- num:14 Thread-2-- num:13 Thread-3-- num:12 Thread-1-- num:13 Thread-2-- num:11 Thread-1-- num:10 Thread-3-- num:10 Thread-2-- num:9 Thread-1-- num:7 Thread-3-- num:8 Thread-2-- num:6 Thread-3-- num:5 Thread-1-- num:5 Thread-2-- num:4 Thread-3-- num:3 Thread-1-- num:2 Thread-2-- num:1 Thread-1-- num:0 Thread-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(); } }