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了
}
原文地址:https://www.cnblogs.com/yanghuiping/p/5570319.html