❶ java多線程中await和wait的區別
其實await和wait的用法差不多。await是wait改進過來,現在開發一多半都用await,因為await加入了lock方法
lock
替代了
synchronized
方法和語句的使用
❷ java 如何實現等待子線程結束
有多種實現方式,下面列出兩種。
第一種:實現Callable類,使用有返回值的線程,只有線程執行完成後才會返回結果。
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Random;
importjava.util.concurrent.*;
publicclassMain{
//初始化一個容量為10的線程池
=Executors.newFixedThreadPool(10);
publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{
List<Future<String>>futures=newArrayList<>();
for(inti=0;i<3;i++){
MyThreadthread=newMyThread("線程"+i);
futures.add(pool.submit(thread));
}
for(Future<String>future:futures){
Stringname=future.get();
System.out.println(name+"執行完成...");
}
System.out.println("所有線程執行完成!");
}
}
<String>{
privateStringname;
publicMyThread(Stringname){
this.name=name;
}
@Override
publicStringcall()throwsException{
//TODO執行業務
//隨機延遲,模擬線程耗時
Thread.sleep(1000+newRandom().nextInt(2000));
returnname;
}
}
第二種:使用CountDownLatch實現線程計數,代碼如下:
importjava.util.Random;
importjava.util.concurrent.CountDownLatch;
importjava.util.concurrent.ExecutionException;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassMain2{
//初始化一個容量為10的線程池
=Executors.newFixedThreadPool(10);
publicstaticvoidmain(String[]args)throwsInterruptedException{
intthreadCount=3;
//初始化CountDownLatch,用於線程計數
CountDownLatchlatch=newCountDownLatch(threadCount);
for(inti=0;i<threadCount;i++){
MyThreadthread=newMyThread("線程"+i,latch);
pool.execute(thread);
}
//阻塞當前線程,CountDownLatch計數減為0時表示所有線程都執行完畢,才會釋放主線程的阻塞
latch.await();
System.out.println("所有線程執行完成!");
}
}
{
privateStringname;
privateCountDownLatchlatch;
publicMyThread(Stringname,CountDownLatchlatch){
this.name=name;
this.latch=latch;
}
@Override
publicvoidrun(){
//TODO執行業務
//隨機延遲,模擬線程耗時
try{
Thread.sleep(1000+newRandom().nextInt(2000));
}catch(InterruptedExceptione){
}
//計數減一
latch.countDown();
System.out.println(name+"執行完畢...");
}
}
❸ 如何等待java線程池中所有任務完成
你可以使用這個CountDownLatch
publicclassCountDownLatchDemo{
=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");
publicstaticvoidmain(String[]args)throwsInterruptedException{
CountDownLatchlatch=newCountDownLatch(2);//兩個工人的協作
Workerworker1=newWorker("zhangsan",5000,latch);
Workerworker2=newWorker("lisi",8000,latch);
worker1.start();//
worker2.start();//
latch.await();//等待所有工人完成工作
System.out.println("allworkdoneat"+sdf.format(newDate()));
}
{
StringworkerName;
intworkTime;
CountDownLatchlatch;
publicWorker(StringworkerName,intworkTime,CountDownLatchlatch){
this.workerName=workerName;
this.workTime=workTime;
this.latch=latch;
}
publicvoidrun(){
System.out.println("Worker"+workerName+"doworkbeginat"+sdf.format(newDate()));
doWork();//工作了
System.out.println("Worker"+workerName+"doworkcompleteat"+sdf.format(newDate()));
latch.countDown();//工人完成工作,計數器減一
}
privatevoiddoWork(){
try{
Thread.sleep(workTime);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
❹ java實現生產者和消費者問題的幾種方式
生產者消費者問題是多線程的一個經典問題,它描述是有一塊緩沖區作為倉庫,生產者可以將產品放入倉庫,消費者則可以從倉庫中取走產品。
解決生產者/消費者問題的方法可分為兩類:
採用某種機制保護生產者和消費者之間的同步;
在生產者和消費者之間建立一個管道。
第一種方式有較高的效率,並且易於實現,代碼的可控制性較好,屬於常用的模式。第二種管道緩沖區不易控制,被傳輸數據對象不易於封裝等,實用性不強。
在Java中有四種方法支持同步,其中前三個是同步方法,一個是管道方法。
wait() / notify()方法
await() / signal()方法
BlockingQueue阻塞隊列方法
PipedInputStream / PipedOutputStream
通過 wait() / notify()方法實現:
wait() / nofity()方法是基類Object的兩個方法:
wait()方法:當緩沖區已滿/空時,生產者/消費者線程停止自己的執行,放棄鎖,使自己處於等等狀態,讓其他線程執行。
notify()方法:當生產者/消費者向緩沖區放入/取出一個產品時,向其他等待的線程發出可執行的通知,同時放棄鎖,使自己處於等待狀態。
通過await() / signal()方法實現:
await()和signal()的功能基本上和wait() / nofity()相同,完全可以取代它們,但是它們和新引入的鎖定機制Lock直接掛鉤,具有更大的靈活性。通過在Lock對象上調用newCondition()方法,將條件變數和一個鎖對象進行綁定,進而控制並發程序訪問競爭資源的安全。
通過BlockingQueue方法實現:
它是一個已經在內部實現了同步的隊列,實現方式採用的是我們第2種await() / signal()方法。它可以在生成對象時指定容量大小。它用於阻塞操作的是put()和take()方法:
put()方法:類似於我們上面的生產者線程,容量達到最大時,自動阻塞。
take()方法:類似於我們上面的消費者線程,容量為0時,自動阻塞。
❺ JAVA 中signal和await 的使用
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
private static LinkedList<String> msglink = new LinkedList<String>();
private Lock lock = new ReentrantLock(true);
public Condition empty = lock.newCondition();
public static void main(String[] args) {
Test t = new Test();
t.startServer();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.onReceiveMsg("hello");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("第二個消息");
t.onReceiveMsg("hello2");
}
private void startServer() {
HandThread t = new Test.HandThread();
t.start();
}
public void onReceiveMsg(String message) {
lock.lock();
msglink.add(message);
empty.signal();
lock.unlock();
}
public class HandThread extends Thread {
public void run() {
while (true) {
lock.lock();
try {
while (msglink.size() == 0) {
System.out.println("暫無主動通知消息");
empty.await();
}
System.out.println("msglink:" + msglink.size());
String msg = msglink.removeFirst();
System.out.println(msg);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}
我猜你出錯的原因應該是里的empty和HandThread的不是同一個.lock是一個線程同步鎖對象,lock方法是獲取鎖,這樣別的線程需要獲取相同鎖就必須等他調用unlock或者其他可以釋放鎖的方法後才可以。
❻ Java中阻塞和等待的區別
定義解釋
阻塞:當一個線程試圖獲取一個內部的對象鎖(非java.util.concurrent庫中的鎖),而該鎖被其他線程持有,則該線程進入阻塞狀態。
等待:當一個線程等待另一個線程通知調度器一個條件時,該線程進入等待狀態。例如調用:Object.wait()、Thread.join()以及等待Lock或Condition。
可以通過代碼與JConsole來驗證
驗證阻塞
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
// 等待主線程獲取鎖
Thread.sleep(10000);
// 請求locker對象的內部鎖
synchronized (locker) {
System.out.println("Get locker");
}
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}, "Blocked Thread");
thread.start();
// 請求locker內部對象鎖
synchronized (locker) {
// 始終持有locker對象的內部鎖
while (true) {
;;
}
}
}
❼ Java中線程怎麼同步
1、使用線程類自帶的join方法,將子線程加入到主線程,在子線程執行完之後,在執行主線程邏輯。
例如
[java]view plain
publicstaticvoidcallableDemo()
throwsInterruptedException
{
System.out.println("=========TestwithCallable=====");
List<Callable<Integer>>callList=newArrayList<Callable<Integer>>();
ExecutorServiceexec=Executors.newFixedThreadPool(2);
//採用匿名內部類實現
callList.add(newCallable<Integer>()
{
publicIntegercall()
throwsException
{
System.out.println("SubWorkerworker1doworkbeginat"+sdf.format(newDate()));
newThreadWaitDemo().doSomeWork();//做實際工作
System.out.println(""
+sdf.format(newDate()));
return0;
}
});
callList.add(newCallable<Integer>()
{
publicIntegercall()
throwsException
{
System.out.println("SubWorkerworker2doworkbeginat"+sdf.format(newDate()));
newThreadWaitDemo().doSomeWork();//做實際工作
System.out.println(""
+sdf.format(newDate()));
return0;
}
});
exec.invokeAll(callList);
exec.shutdown();
doSuperWork();
}