1、Java多線程應用

Java多線程應用
  1. 什麼是進程?
    進程是操作系統的結構,是一次程序的執行,是程序在一個數據集合運行的過程,是系統的進行資源分配和調度的獨立單位?
  2. 什麼是線程?
    線程是進程中具體的搬運工,由進行分配資源進行調度,單個線程必須一個執行完成後,才能執行另外一個,但是多線程操作系統windows,就可以在一個任務執行處於等待的時候,cpu空閒的時間去執行另外一個任務,各個任務之前的快速切換,可以造成,多任務同時執行的效果。
  3. 實現線程的方法
    3.1 繼承Thread類

package threadMainTest;
public class ManyThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
}
}

 主方法調用

package threadMainTest;

public class ThreadMainTest {
	public static void main(String[] args) throws InterruptedException {
	ManyThread mT = new ManyThread();
	}
}

3.2 實現Runnable接口
4. package threadMainTest;
5.
6. public class MyRunnable implements Runnable{
7.
8. @Override
9. public void run() {
10. System.out.println(“使用實現runnable方式來實現線程”);
11. }
12.
13. }
 主方法調用
package threadMainTest;
public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
MyRunnable mr = new MyRunnable();
Thread tr = new Thread(mr);
tr.start();
}
}
 因爲Thread類是繼承的Runnable接口,所以這兒Thread構造函數,不僅可以傳入一個Runnable對象,還可以傳入一個Thread對象。
4. 線程常用的方法
4.1 currentThread()方法,返回當前代碼塊正在被哪個線程調用
5 package threadMainTest;
6 public class MyThread extends Thread{
7 public MyThread() {
8 System.out.println(“CountOperate begin”);
9 System.out.println(“Thread.currentThread().getName()=”+Thread.currentThread().getName());
10 System.out.println(“this.getName()”+this.getName());
11 System.out.println(“CountOperate end”);
12 }
13 @Override
14 public void run() {
15 System.out.println(“run begin”);
16 System.out.println(“Thread.currentThread().getName()=”+Thread.currentThread().getName());
17 System.out.println(“this.getName()=”+this.getName());
18 System.out.println(“run end”);
19 }
20 }
 主方法調用
21 MyThread my = new MyThread();
22 Thread t = new Thread(my);
23 t.setName(“A”);
24 t.start();
 結果展示
25 CountOperate begin
26 Thread.currentThread().getName()=main
27 this.getName()Thread-0
28 CountOperate end
29 run begin
30 Thread.currentThread().getName()=A
31 this.getName()=Thread-0
32 run end
 如果將主方法代碼修改爲下面
MyThread my = new MyThread();
Thread t = new Thread(my);
t.setName(“A”);
t.start();
my.setName(“A”);
my.start();
 結果展示
CountOperate begin
Thread.currentThread().getName()=main
this.getName()Thread-0
CountOperate end
run begin
Thread.currentThread().getName()=A
this.getName()=A
run end
run begin
Thread.currentThread().getName()=A
this.getName()=A
4.2 isActive()方法,用於顯示線程的活躍狀態,活躍狀態就是線程已經啓動並且尚未終止。線程處於正在運行或者存在運行的狀態,就認爲線程是存活的,如果存活返回true,否則返回false.
4.3 Sleep()是在指定的毫秒數內,讓正在執行的線程休眠,this.currentThrad()就是指正在執行的線程
4.4 Getid()取得線程唯一的標識符,即表示線程的ID值
5. 停止線程
5.1 stop(),suspend(),resume(),都可以用於終止線程,但是他們都是強制終止線程,不安全,所以已經被移除(deprecated),在未來的JAVA版本中也將不可以使用,目前使用Interrupt(),終止線程,但是不會終止正在運行的線程,需要加入一個判斷才能完成線程的終止。
package threadMainTest;

public class isThreadActive extends Thread{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(“i=”+ i++);
}
}
}
 主函數調用
package threadMainTest;

public class isThreadActive extends Thread{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(“i=”+ i++);
}
}
}
 結果展示
i=378
i=380
i=382
i=384
i=386
i=388
i=390
i=392
i=394
i=396
i=398
i=400
i=402
i=404
線程並沒有被關閉,是因爲interrupt()不能關閉正在運行的線程
5.2 interrupted() 測試當前線程是否已經被中斷(當判斷完畢後,如果線程被中斷,會清楚當前被中斷的狀態),inInterrupted()測試線程是否已經被中斷.沒有清除功能
6. package threadMainTest;
7.
8. public class Run2 {
9. public static void main(String[] args) {
10. Thread.currentThread().interrupt();
11. System.out.println(“是否停止1?”+Thread.interrupted());
12. System.out.println(“是否停止2?”+Thread.interrupted());
13. }
14. }
 結果展示
15. 是否停止1?true
16. 是否停止2?false
 如果是inInterrupted()
17. package threadMainTest;
18.
19. public class Run2 {
20. public static void main(String[] args) {
21. try {
22. isThreadActive thread = new isThreadActive();
23. thread.start();
24. Thread.sleep(5);
25. thread.interrupt();
26. System.out.println(“是否停止1?”+thread.isInterrupted());
27. System.out.println(“是否停止2?”+thread.isInterrupted());
28. } catch (InterruptedException e) {
29.
30. e.printStackTrace();
31. }
32. }
33. }
 結果展示
34. i=637
35. 是否停止1?true
36. 是否停止2?true
37. i=638
38. i=639
5.3 調用interrupt方法後,後for後面的語句還是在運行(如何使線程停止,程序不運行)
6 package thread;
7
8 public class ThreadTest extends Thread{
9 @Override
10 public void run() {
11 int time = 0;
12 for (int i = 0; i < 500000; i++) {
13 if(this.interrupted()) {
14 System.out.println("已經是停止狀態了,我要退出了 ");
15 break;
16 }
17 System.out.println("i = " + (i+1));
18 }
19 System.out.println(“還是在運行”);
20 }
21 }
 展示結果
22 i = 394330
23 i = 394331
24 i = 394332
25 已經是停止狀態了,我要退出了
26 還是在運行
27 end!

 如何使停止線程後程序就不在運行,使用異常退出
28 package thread;
29 public class ThreadTest extends Thread{
30 @Override
31 public void run() {
32 super.run();
33 try {
34 for (int i = 0; i < 500000; i++) {
35 if(this.interrupted()) {
36 System.out.println("已經是停止狀態了,我要退出了 ");
37 throw new InterruptedException();
38 }
39 System.out.println("i = " + (i+1));
40 }
41 System.out.println(“還是在運行”);
42 } catch (InterruptedException e) {
43 System.out.println(“進入了線程的異常捕獲方法”);
44 e.printStackTrace();;
45 }
46 }
47 }
 主方法
48 package thread;
49
50 public class ThreadMainTest {
51 public static void main(String[] args) {
52 try {
53 ThreadTest thread = new ThreadTest();
54 thread.start();
55 Thread.sleep(100);
56 thread.interrupt();
57 } catch (InterruptedException e) {
58 System.out.println(“main catch”);
59 e.printStackTrace();
60 }
61 System.out.println(“end!”);
62 }
63 }

 結果展示
64 i = 341617
65 已經是停止狀態了,我要退出了
66 進入了線程的異常捕獲方法
67 end!
68 java.lang.InterruptedException
69 at thread.ThreadTest.run(ThreadTest.java:11)
 如何停止沉睡中的線程
package thread;

public class ThreadTest extends Thread{
@Override
public void run() {
super.run();
try {
System.out.println(“run begin”);
Thread.sleep(200000);
System.out.println(“run end”);
} catch (InterruptedException e) {
System.out.println(“線程停止,目前狀態爲:” + this.isInterrupted());
e.printStackTrace();
}
}
}
 展示結果:
run begin
線程停止,目前狀態爲:false
end!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at thread.ThreadTest.run(ThreadTest.java:9)
 如果先執行interrupt停止再sleep會怎麼樣
package thread;

public class ThreadTest extends Thread{
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 500; i++) {
System.out.println("i= " + (i+1));
}
System.out.println(“run begin”);
Thread.sleep(200000);
System.out.println(“run end”);
} catch (InterruptedException e) {
System.out.println(“先停止,再遇到Sleep,然後進入catch”);
e.printStackTrace();
}
}
}
主方法
package thread;

public class ThreadMainTest {
public static void main(String[] args) {
ThreadTest thread = new ThreadTest();
thread.start();
thread.interrupt();
System.out.println(“end!”);
}
}
 使用return停止線程
package thread;

public class ThreadTest extends Thread{
@Override
public void run() {
super.run();
while(true) {
if(this.isInterrupted()) {
System.out.println(“停止了”);
return;
}
System.out.println("time= " + System.currentTimeMillis());
}

}

}
主方法:
package thread;

public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
ThreadTest thread = new ThreadTest();
thread.start();
Thread.sleep(2000);
thread.interrupt();
}
}
結果展示:
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
停止了
 不過還是建議用拋異常的方式來停止線程,因爲Catch塊中還可以將異常向上拋,使線程停止的事件得以傳播!
6. 暫停線程
6.1 suspend()暫停現場,resume()恢復線程使用
7. package threadMainTest;
8.
9. public class ThreadMainTest {
10. @SuppressWarnings(“deprecation”)
11. public static void main(String[] args) throws InterruptedException {
12. MyThread my = new MyThread();
13. my.start();
14. Thread.sleep(5000);
15. my.suspend();//已經被移除,可以用但是還是有缺陷,在被調用過程中不會釋放所佔用的鎖,容易造成死鎖
16. System.out.println("A= " + System.currentTimeMillis()+ "A= " + my.getI());
17. System.out.println("B= " + System.currentTimeMillis()+ "B= " + my.getI());
18. my.resume();
19. Thread.sleep(5000);
20. my.suspend();
21. System.out.println("C= " + System.currentTimeMillis()+ "C= " + my.getI());
22. System.out.println("D= " + System.currentTimeMillis()+ "D= " + my.getI());
23. }
24. }
 結果展示
25. A= 1542871355220A= -1084856100
26. B= 1542871355220B= -1084856100
27. C= 1542871405220C= 929579568
28. D= 1542871405220D= 929579568
6.2 Yield()放棄當前的CPU,資源,讓給其它任務來佔用CPU
package thread;

public class ThreadTest extends Thread{
@Override
public void run() {
long time = System.currentTimeMillis();
int count = 0 ;
while(count < 500000) {
//Thread.yield();
count ++;
}
long endTime = System.currentTimeMillis();
System.out.println(“用時” + (endTime-time) + “毫秒”);
}
}
 結果顯示:

 使用Thread.yield()後,把CPU讓給其他資源,導致速度變慢

6.3 優先級
6.3.1 繼承性
線程的優先級具有繼承性,A調用B線程,所以B線程的優先級跟A線程一樣
package threadMainTest;

public class MyThread extends Thread{
@Override
public void run() {
System.out.println("MyThread run is priority = " + this.getPriority());
}
}
 主方法調用
package threadMainTest;

public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("main thread begin priority = " + Thread.currentThread().getPriority());
Thread.currentThread().setPriority(6);
System.out.println("main thread begin priority = " + Thread.currentThread().getPriority());
new MyThread().start();
}
}
 結果
main thread begin priority = 5
main thread begin priority = 6
MyThread run is priority = 6
6.3.2使用setPriority()方法設置優先級
高優先級的線程大部分總是先執完,但是並不代表所有高優先級的線程會限制性,線程的優先級與代碼的調用順序無關,線程執行具有隨機性,不一定每次高的線程都先執行
6.3.3守護線程
守護線程,是伴隨着需要守護的線程的,當最後一個需要守護的線程停止時,守護線程纔會隨着JVM結束,最典型的的就是GC垃圾回收機制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章