java线程
1.线程间通讯
在多线程中,一般会牵扯到线程间的通讯问题,通常的做饭是通过wait和notify方法实现。wait和notify方法是定义在Object类中的,因此会被所有的方法继承。
需要明白Thread.sleep(time)方法和wait方法的区别。Sleep是线程独有的。调用后当前线程会暂停一段时间,具体可以 通过time指定。当时线程暂停时不会释放锁。即占着资源去睡觉。Wait会释放锁。Sleep时间到后会自动开始执行线程。Wait需要另外的线程来通知它,通知的方法为notify或notifyAll。这样他才能重新拥有所并恢复执行。
为了确保wait方法调用的时候拥有锁,wait一般放在synchronized方法或synchronized块中。
Notify方法会唤醒一个等待当前对象锁的线程。如果多个线程等待当前对象的锁,会随机。被唤醒的对象不会立马拥有这个对象锁,需要当前对象放弃这个对象锁后拥有。
wait()和notify()方法要求在调用时线程已经获得了对象的锁,因此对这两个方法的调用需要放在synchronized方法或synchronized块中
一个线程变为一个对象的锁的拥有者是通过下列三种方法:1.执行这个对象的synchronized实例方法。2.执行这个对象的synchronized语句块。这个语句块锁的是这个对象。3.对于Class类的对象,执行那个类的synchronized、static方法。
2.线程返回值
线程返回值一般不叫做线程,而是任务,实现方法是实现Callable接口。执行Callable后,会返回一个Future对象,通过这个对象可以拿到返回结果,已经task是否已经运行完成。例:
package com.yhp.myweb.test.thread; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class TaskWithResult implements Callable<Object>{ private int id; public TaskWithResult(int id){ this.id = id; } @Override public Object call() throws Exception { return "call:"+id; } public static void main(String args[]) throws InterruptedException, ExecutionException{ ExecutorService exec = Executors.newCachedThreadPool(); ArrayList<Future<Object>> results = new ArrayList<Future<Object>>(); for(int i=0;i<10;i++){ results.add(exec.submit(new TaskWithResult(i))); } for(Future<Object> future : results){ System.out.println(future.isDone() + "-" + future.get()); } } //现在Java终于有可返回值的任务(也可以叫做线程)了 //执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了 }