介紹一下線程中基本的方法使用
線程睡眠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作為守護線程就自動停止了。
多線程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");
}
}
我們發現有些輸出並沒有打印全,在執行線程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");
}
}
}
使用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工程化、高性能及分佈式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限 都是大牛帶飛 讓你少走很多的彎路的 群.號是 338549832 對了 小白勿進 最好是有開發經驗
注:加群要求
1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。
2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。
3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。
4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。
5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!
閱讀更多 java開發者 的文章