Java中多線程-多線程中的基本方法

介紹一下線程中基本的方法使用

線程睡眠sleep()

Thread.sleep(毫秒);我們可以通過sleep方法設置讓線程睡眠。可以看到sleep是個靜態方法

public static native void sleep(long var0) throws InterruptedException;
try {
System.out.println(new Date().getSeconds());
Thread.sleep(5000);
System.out.println(new Date().getSeconds());
} catch (InterruptedException e) {
e.printStackTrace();
}

setDaemon守護線程

非守護線程停止,那麼守護線程自動退出

 public static void main(String[] args) {
Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 5; i ++) {
System.out.println("非守護線程");
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
System.out.println("守護線程");
}
}
};
thread2.setDaemon(true);
thread1.start();
thread2.start();

}

可以很明顯的看到thread2本應該執行200次輸出,但是這裡只輸出了幾行。因為當thread1執行完畢後,thread2作為守護線程就自動停止了。

Java中多線程-多線程中的基本方法

Java中多線程

多線程jion

如果執行了jion方法,那麼停止當前線程,先跑執行了jion()的線程。相當於插隊執行。如下,在執行thread2線程的時候,如果i==20的時候,則讓thread1插隊先執行

 public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println("thread1---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
if (i == 20) {
try {
//插隊執行
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
}
}
};
thread1.start();
thread2.start();
}

join()方法也可以傳參數long 毫秒 join(毫秒)

表示讓執行join的線程,插隊執行XXX毫秒,過了時間後,兩個線程交替執行

 public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println("thread1---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
if (i == 20) {
try {
//插隊執行1毫秒
thread1.join(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
}
}
};
thread1.start();
thread2.start();
}

yeild 禮讓線程

yeild會讓出cpu,讓其他線程執行

 public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {

System.out.println( getName() + "---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
if (i % 5 == 0) {
Thread.yield();
}
System.out.println(getName() + "---" + i);
}
}
};
thread1.start();
thread2.start();
}

setPriority給線程設置優先級

默認優先級是5 最小1,最大10

越大優先級越高


public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println( getName() + "---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 500; i ++) {
System.out.println(getName() + "---" + i);
}
}

};
//設置最大的線程優先級最大為10
thread1.setPriority(Thread.MIN_PRIORITY);
//設置最小的線程優先級,最小為1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}

synchronized

同步代碼塊

當多線程併發,多段代碼同時執行的時候。希望在執行其中代碼的時候,cpu不切換線程

不用synchronized的情況

我們來看一下不用synchronized的情況會發生什麼

public class ThreadSynchronied {
public static void main(String[] args) {
final Say say = new Say();
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {

say.say1();
}
}
};
//設置最大的線程優先級最大為10
thread1.setPriority(Thread.MIN_PRIORITY);
//設置最小的線程優先級,最小為1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
class Say {
void say() {
System.out.print("s ");
System.out.print("a ");
System.out.print("y ");
System.out.print("h ");
System.out.print("e ");
System.out.print("l ");
System.out.print("l ");
System.out.println("o");
}
void say1() {
System.out.print("1 ");
System.out.print("2 ");
System.out.print("3 ");
System.out.print("4 ");
System.out.print("5 ");
System.out.print("6 ");
System.out.print("7 ");
System.out.println("8");
}
}
Java中多線程-多線程中的基本方法

Java中多線程

我們發現有些輸出並沒有打印全,在執行線程thread1的過程中,cpu被thread2搶佔。這種情況下,肯定是不符合我們的業務邏輯的。所以我們要保證線程執行了一個完整的方法後,cpu才會被其他線程搶佔

使用synchronized

public class ThreadSynchronied {
public static void main(String[] args) {
final Say say = new Say();
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say1();
}
}
};
//設置最大的線程優先級最大為10
thread1.setPriority(Thread.MIN_PRIORITY);
//設置最小的線程優先級,最小為1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
class Say {
String s = "hahaah";
void say() {

synchronized (s) {
System.out.print("s ");
System.out.print("a ");
System.out.print("y ");
System.out.print("h ");
System.out.print("e ");
System.out.print("l ");
System.out.print("l ");
System.out.println("o");
}
}
void say1() {
synchronized (s) {
System.out.print("1 ");
System.out.print("2 ");
System.out.print("3 ");
System.out.print("4 ");
System.out.print("5 ");
System.out.print("6 ");
System.out.print("7 ");
System.out.println("8");
}
}
}
Java中多線程-多線程中的基本方法

Java中多線程

使用synchronized同步代碼塊後,就發現不會出現上述情況了

同步方法

public class ThreadSynchroniedMethod {
public static void main(String[] args) {
final Say say = new Say();
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say1();
}
}
};
//設置最大的線程優先級最大為10
thread1.setPriority(Thread.MIN_PRIORITY);
//設置最小的線程優先級,最小為1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
class Say {
//在方法上加鎖
static synchronized void say() {
System.out.print("s ");
System.out.print("a ");
System.out.print("y ");
System.out.print("h ");
System.out.print("e ");

System.out.print("l ");
System.out.print("l ");
System.out.println("o");
}
static void say1() {
synchronized (Say.class) {
System.out.print("1 ");
System.out.print("2 ");
System.out.print("3 ");
System.out.print("4 ");
System.out.print("5 ");
System.out.print("6 ");
System.out.print("7 ");
System.out.println("8");
}
}
}

同步方法指的就是在方法上加鎖

靜態同步方法的所對象是該類的字節碼對象

非靜態的同步方法鎖對象是this

多個線程使用同一資源鎖,容易造成死鎖

什麼是死鎖?

死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。 

線程安全類

Vector

StringBuffer

HashTable

線程不安全

ArrayList

StringBuilder

HashSet

java.util.Collections中有synchronizedList等方法,支持我們把線程不安全的集合轉成線程安全的

Java中多線程-多線程中的基本方法

Java中多線程

學習筆記

多次啟動一個線程是非法的

加Java架構師進階交流群獲取Java工程化、高性能及分佈式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限 都是大牛帶飛 讓你少走很多的彎路的 群.號是 338549832 對了 小白勿進 最好是有開發經驗

注:加群要求

1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!


分享到:


相關文章: