91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

多線程for循環效率的問題怎么解決

發布時間:2021-06-17 14:45:53 來源:億速云 閱讀:254 作者:chen 欄目:開發技術

本篇內容介紹了“多線程for循環效率的問題怎么解決”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

多線程解決for循環效率問題

在for里面,如果執行一次for里面的內容所需時間比較長,可以使用線程池來提高for循環的效率

public class TreadFor {
private static final int loopNum = 1*10;  
    public static void main(String args[]) throws InterruptedException {  
    	TreadFor TestThreadPool = new TreadFor();  
        long bt = System.currentTimeMillis();  
        List<String> list = new ArrayList<>();
        list.add("0");
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("7");
        list.add("8");
        list.add("9");
        TestThreadPool.m1(list);  
        long et2 = System.currentTimeMillis();  
        System.out.println("[1]耗時:"+(et2 - bt)+ "ms");  
        Thread thread = new Thread();  
        long at = System.currentTimeMillis();  
        TestThreadPool.m2();
        long et3 = System.currentTimeMillis();
        System.out.println("[2]耗時:"+(et3 - at)+ "ms");
    }  
  
    public void m1( List<String> list) {
        ExecutorService pool = Executors.newCachedThreadPool();  
        for (int i = 0; i < list.size(); i++) {
        	String str = list.get(i);
        	System.out.println(list.get(i));
            Runnable run = new Runnable() {  
                public void run() {  
                    try {  
                        new Thread().sleep(1000);
                        //模擬耗時操作
                    	System.out.println("[1]" + Thread.currentThread().getName()+"----"+str);
                    } catch (Exception e) {  
                    }  
                }  
            }; 
            pool.execute(run);  
		
		}
        System.out.println("[1] done!");
        pool.shutdown();  
    }  
  
    public void m2() { 
    	AtomicInteger connectionIds = new AtomicInteger(0);
        for (int index = 0; index < loopNum; index++) {  
            try {  
                new Thread().sleep(1000);  //模擬耗時操作
                System.out.println("[2]" + Thread.currentThread().getName());
                
            } catch (Exception e) {  
                e.printStackTrace();  
            } 
        }  
        System.out.println("[2] done!");
    }  
}

其中遍歷list,給方法傳參,參數最終也可以進入的線程里;

運行結果:

多線程for循環效率的問題怎么解決

由打印結果可知:m1方法是用到了多線程的,多線程此時被線程池管理;而m2方法始終是main主線程執行的。

采用先把要執行的“耗時”內容放到一個線程的執行主體(run方法)里面,再用線程池執行該線程,可大大減少for循環的耗時。

但這種情況不適合for次數較大的情形,因為每循環一次,就開辟一個線程,開銷較大。

注意這種不叫高并發,只是相當于原來由一個工人干的活現在由多個工人協作完成一樣。

Java 多個線程交替循環執行

有些時候面試官經常會問,兩個線程怎么交替執行呀,如果是三個線程,又怎么交替執行呀,這種問題一般人還真不一定能回答上來。多線程這塊如果理解的不好,學起來是很吃力的,更別說面試了。

下面我們就來剖析一下怎么實現多個線程順序輸出。

兩個線程循環交替打印

//首先我們來看一種比較簡單的方式
public class ThreadCq {
 public static void main(String[] args) {
   Stack<Integer> stack = new Stack<>();
   for(int i=1;i<100;i++) {
    stack.add(i);
   }
   Draw draw = new Draw(stack);
   new Thread(draw).start();
   new Thread(draw).start();
 }
}
 
class Draw implements Runnable{
 private Stack<Integer> stack;
 public Draw(Stack<Integer> stack) {
  this.stack = stack;
 }
 
 @Override
 public void run() {
  while(!stack.isEmpty()) {
   synchronized (this) {
    notify();
    System.out.println(Thread.currentThread().getName()+"---"+stack.pop());
    try {
     wait();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
 }
}

這種方式是用Condition對象來完成的:

public class ThreadCq3 {
 //聲明一個鎖
 static ReentrantLock lock = new ReentrantLock();
 public static void main(String[] args) {
  //創建兩個Condition對象
  Condition c1 = lock.newCondition();
  Condition c2 = lock.newCondition();
  Stack<Integer> stack = new Stack<>();
  for (int i = 0; i <= 100; i++) {
   stack.add(i);
  }
 
  new Thread(() -> {
   try {
    Thread.sleep(500);
   } catch (InterruptedException e1) {
    e1.printStackTrace();
   }
   while (true) {
    lock.lock();
    // 打印偶數
    try {
     if (stack.peek() % 2 != 0) {
      c1.await();
     }
     System.out.println(Thread.currentThread().getName() + "-----" + stack.pop());
     c2.signal();
    } catch (InterruptedException e) {
     e.printStackTrace();
    } finally {
     lock.unlock();
    }
   }
  }).start();
  
  new Thread(() -> {
   while (true) {
    try {
     Thread.sleep(500);
    } catch (InterruptedException e1) {
     e1.printStackTrace();
    }
    lock.lock();
    try {
     // 打印奇數
     if (stack.peek() % 2 != 1) {
      c2.await();
     }
     System.out.println(Thread.currentThread().getName() + "-----" + stack.pop());
     c1.signal();
    } catch (InterruptedException e) {
     e.printStackTrace();
    } finally {
     lock.unlock();
    }
   }
  }).start();
 }
}

這種方式是通過Semaphore來實現的:

public class ThreadCq4 {
 //利用信號量來限制
 private static Semaphore s1 = new Semaphore(1);
 private static Semaphore s2 = new Semaphore(1);
 public static void main(String[] args) {
  
  try {
   //首先調用s2為 acquire狀態
   s1.acquire();
//   s2.acquire();  調用s1或者s2先占有一個
  } catch (InterruptedException e1) {
   e1.printStackTrace();
  }
  
  new Thread(()->{
   while(true) {
    try {
     s1.acquire();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    try {
     Thread.sleep(500);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println("A");
    s2.release();
   }
  }).start();
  
  new Thread(()->{
   while(true) {
    try {
     s2.acquire();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    try {
     Thread.sleep(500);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println("B");
    s1.release();
   }
  }).start();
 }
}

上面就是三種比較常用的,最常用的要屬第一種和第二種。

三個線程交替打印輸出

上面我們看了兩個線程依次輸出的實例,這里我們來看看三個線程如何做呢。

public class LockCond {
 private static int count = 0;
 private static Lock lock = new ReentrantLock();
 public static void main(String[] args) {
  Condition c1 = lock.newCondition();
  Condition c2 = lock.newCondition();
  Condition c3 = lock.newCondition();
  new Thread(()->{
   while(true) {
    lock.lock();
    try {
     while(count %3 != 0) {
      //剛開始count為0  0%3=0 所以此線程執行  執行完之后 喚醒現成2,由于此時count已經進行了++,所有while成立,c1進入等待狀態,其他兩個也一樣
      c1.await();
     }
     System.out.println(Thread.currentThread().getName()+"========:A");
     count++;
     //喚醒線程2
     c2.signal(); 
    } catch (InterruptedException e) {
     e.printStackTrace();
    } finally {
     lock.unlock();
    }
   }
  }) .start();
  
  new Thread(()->{
   while(true) {
    lock.lock();
    try {
     while(count %3 != 1) {
      c2.await();
     }
     System.out.println(Thread.currentThread().getName()+"========:B");
     count++;
     //喚醒線程3
     c3.signal();
    } catch (InterruptedException e) {
     e.printStackTrace();
    } finally {
     lock.unlock();
    }
   }
  }) .start();
  
  new Thread(()->{
   while(true) {
    lock.lock();
    try {
     while(count %3 != 2) {
      c3.await();
     }
     System.out.println(Thread.currentThread().getName()+"========:C");
     count++;
     //喚醒線程1
     c1.signal();
    } catch (InterruptedException e) {
     e.printStackTrace();
    } finally {
     lock.unlock();
    }
   }
  }) .start();
 }
}

三個線程的也可以寫三種,這里寫一種就行了,寫法和上面兩個線程的都一樣。大家可以自己試一下。

Condition介紹

我們在沒有學習Lock之前,使用的最多的同步方式應該是synchronized關鍵字來實現同步方式了。配合Object的wait()、notify()系列方法可以實現等待/通知模式。Condition接口也提供了類似Object的監視器方法,與Lock配合可以實現等待/通知模式,但是這兩者在使用方式以及功能特性上還是有差別的。Object和Condition接口的一些對比。摘自《Java并發編程的藝術》

多線程for循環效率的問題怎么解決

Condition接口常用方法

condition可以通俗的理解為條件隊列。當一個線程在調用了await方法以后,直到線程等待的某個條件為真的時候才會被喚醒。這種方式為線程提供了更加簡單的等待/通知模式。Condition必須要配合鎖一起使用,因為對共享狀態變量的訪問發生在多線程環境下。一個Condition的實例必須與一個Lock綁定,因此Condition一般都是作為Lock的內部實現。

await() :造成當前線程在接到信號或被中斷之前一直處于等待狀態。

await(long time, TimeUnit unit) :造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態。

awaitNanos(long nanosTimeout) :造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態。返回值表示剩余時間,如果在nanosTimesout之前喚醒,那么返回值 = nanosTimeout - 消耗時間,如果返回值 <= 0 ,則可以認定它已經超時了。

awaitUninterruptibly() :造成當前線程在接到信號之前一直處于等待狀態。【注意:該方法對中斷不敏感】。

awaitUntil(Date deadline) :造成當前線程在接到信號、被中斷或到達指定最后期限之前一直處于等待狀態。如果沒有到指定時間就被通知,則返回true,否則表示到了指定時間,返回返回false。

signal() :喚醒一個等待線程。該線程從等待方法返回前必須獲得與Condition相關的鎖。

signal()All :喚醒所有等待線程。能夠從等待方法返回的線程必須獲得與Condition相關的鎖。

Semaphore介紹

Semaphore 是 synchronized 的加強版,作用是控制線程的并發數量。就這一點而言,單純的synchronized 關鍵字是實現不了的。他可以保證某一個資源在一段區間內有多少給線程可以去訪問。

多線程for循環效率的問題怎么解決

多線程for循環效率的問題怎么解決

從源碼我們可以看出來,它new了一個靜態內部類,繼承Sync接口。他同時也提供了一些構造方法

多線程for循環效率的問題怎么解決

比如說通過這個構造方法可以創建一個是否公平的Semaphore類。

“多線程for循環效率的問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

镇安县| 松桃| 汶上县| 承德市| 阿瓦提县| 衡山县| 竹溪县| 临西县| 资兴市| 承德县| 武平县| 锦屏县| 环江| 明光市| 双流县| 中西区| 鄂伦春自治旗| 沙河市| 阿拉善右旗| 团风县| 莱西市| 靖西县| 大田县| 宝应县| 应用必备| 五大连池市| 修水县| 邯郸县| 昌宁县| 万山特区| 绿春县| 遵化市| 普宁市| 通榆县| 巴里| 台中市| 忻城县| 永寿县| 鹰潭市| 仁化县| 昭通市|