❶ 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();
}