Thread2(多線程)再接再厲ヾ(◍°∇°◍)ノ゙

多線程小結:

1.多線程併發訪問同一段資源,會形成搶的現象,由於線程切換的時機不確定,可能會導致執行代碼順序混亂,嚴重時會導致系統癱瘓。(取個豆子桌子還欠幾百萬)

2. 方法被synchronized修飾以後爲同步方法,即多個線程不能同時進入方法內部執行。對於成員方法而言,synchronized會在線程調用該方法時將方法所屬對象枷鎖,其他線程在執行該方法時由於執行方法的線程沒有釋放鎖,所以只能在方法外阻塞,直到持有方法鎖的線程將方法執行完畢,所以解決多線程併發執行安全問題的辦法就是變搶位排隊。

3.同步塊,有效的縮小同步範圍可以保證併發安全的同時,提升併發的效率。(逛商場大家一起逛,試衣間排隊)

 同步塊可以要求多個線程對該塊內的代碼排隊執行,但是前提是同步監視器對象(即上鎖對象)要求多個線程看到的必須是同一個兩個試衣間或者鎖的是new Object()都不行,synchronized(同步監視對象){需要同步的代碼}
所謂同步:多個線程必須排隊執行
所謂異步:多個線程可以同時執行

4. 靜態方法的同步:當一個靜態方法被synchronized修飾以後,那麼該方法即爲同步方法,由於靜態方法全局就一所以同步的靜態方法一定具有同步效果和對象無關

5.互斥鎖
synchronized也叫互斥鎖,使用它修飾的多段代碼,只要他們的同步監視器對象相同,那麼這幾段代碼間就是互斥關係,即多個線程不能同時執行這些代碼,關鍵是選取對象是一個,同步鎖和互斥鎖的差異,修飾的是否是同一段代碼
,但是選取的對象一定是一個。

6.將集合或者Map轉化爲線程安全的,ArrayList 和LinkedList都不是線程安全的,API手冊上有說明就算是線程安全的集合那麼對於元素的操作,如add,remove等方法都不與迭代器遍歷做互斥,需要自行維護互斥關係

7.線程池:控制線程數量,重用線程。當我們發現需要創建大量線程或者發現線程會頻繁的創建或銷燬時就應當考慮使用線程池來維護線程,4種創建方式:
 1.彈性的
 Executors.newCashedThreadPool();
   2.固定數量的
   Executors.newFixedThreadPool(n);
 3.可延遲定期執行的
   Executors.newScheduledThreadPool();
 4.單個線程
   Exeutors.newSingleThreadExecutor();

***************************************************************************************************************

取豆子欠了幾百萬.......

public class demo1 {
public static void main(String[] args) {
final Table table=new Table();
Thread t1=new Thread(){
public void run(){
while(true){
int bean=table.getBean();
Thread.yield();
System.out.println(getName()+":"+bean);
}
}
};
Thread t2=new Thread(){
public void run(){
while(true){
int bean=table.getBean();
Thread.yield();
System.out.println(getName()+":"+bean);
}
}
};
t1.start();
t2.start();
}
}
class Table{
//桌子上有20個豆子
private int beans=20;
public synchronized int getBean(){
if(beans==0){
throw new RuntimeException("沒有豆子了!");
}
Thread.yield();
return beans--;
}
}

***********************************************************************************************************

線程安全情況下減少時間

public class demo2 {
public static void main(String[] args) {
final Shop shop=new Shop();
Thread t1=new Thread(){
public void run(){
shop.buy();
}
};
Thread t2=new Thread(){
public void run(){
shop.buy();
}
};
t1.start();
t2.start();
}
}
class Shop{
public void buy(){
Thread t=Thread.currentThread();
try {
System.out.println(t.getName()+";正在挑衣服");
Thread.sleep(5000);
synchronized(new Object()){
System.out.println(t.getName()+";正在試衣服");
Thread.sleep(5000);
}
System.out.println(t.getName()+";結賬離開");
} catch (Exception e) {
e.printStackTrace();
}
}
}

***********************************************************************************

synchronized修飾靜態方法

public class demo3 {
public static void main(String[] args) {
final Foo f1=new Foo();
final Foo f2=new Foo();

Thread t1=new Thread(){
public void run(){
Foo.dosome();//跟對象無關
}
};
Thread t2=new Thread(){
public void run(){
Foo.dosome();
}
};
t1.start();
t2.start();
}
}
class Foo{
public synchronized static void dosome(){
try {
Thread t=Thread.currentThread();
System.out.println(t.getName()+":準備開始!");
Thread.sleep(5000);
System.out.println(t.getName()+":結束完畢!");
} catch (Exception e) {
e.printStackTrace();
}
}
}

***************************************************************************************************

public class demo4 {
public static void main(String[] args) {
final Boo boo=new Boo();
Thread t1=new Thread(){
public void run(){
boo.methodA();
}
};
Thread t2=new Thread(){
public void run(){
boo.methodB();
}
};
t1.start();
t2.start();
}
}
class Boo{
public synchronized void methodA(){
try {
Thread t=Thread.currentThread();
System.out.println(t.getName()+":A開始了");
Thread.sleep(5000);
System.out.println(t.getName()+":A結束了");
} catch (Exception e) {

}
}
public synchronized void methodB(){
try {
Thread t=Thread.currentThread();
System.out.println(t.getName()+":B開始了");
Thread.sleep(5000);
System.out.println(t.getName()+":B結束了");
} catch (Exception e) {

}
}
}

*************************************************************************************************

轉換爲線程安全的

public class demo5 {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
System.out.println(list);
//將給定集合轉化爲線程安全的集合
list=Collections.synchronizedList(list);
System.out.println(list);

Set<String> set=new HashSet<String>(list);
System.out.println(set);
//將set集合轉化爲線程安全的
set=Collections.synchronizedSet(set);
System.out.println(set);

Map<String,Integer> map=new HashMap<String,Integer>();
map.put("語文",98);
map.put("數學", 97);
map.put("英語",95);
System.out.println(map);
//將map轉換爲線程安全的
map=Collections.synchronizedMap(map);
System.out.println(map);
}
}

***********************************************************************************************

線程池的方法

public class demo6 {
public static void main(String[] args) {
ExecutorService threadPool=Executors.newFixedThreadPool(2);

for(int i=0;i<5;i++){
Runnable runn=new Runnable(){
public void run(){
Thread t=Thread.currentThread();
try {
System.out.println(t+":正在運行線程!");
Thread.sleep(5000);
System.out.println(t+":運行完畢!");
} catch (InterruptedException e) {
System.out.println("線程被中斷了");
}
}
};
threadPool.execute(runn);
System.out.println("指派了一個任務交給線程池");
}
threadPool.shutdownNow();
System.out.println("停止線程池了");
}
}


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