从任务中返回值

import java.util.ArrayList;
import java.util.concurrent.*;

class TaskWithResult implements Callable<String> { //要想得到返回值可以实现Callable接口,类型参数是返回值的类型
    private int id;
    public TaskWithResult(int id) {
        this.id = id;
 }
    @Override
    public String call() throws Exception { //实现call()方法,而不是run()
        return "result of TaskWithResult" + id;
 }
}
public class CallableDemo {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool(); 
        ArrayList<Future<String>> results = new ArrayList<>(); //submit方法会产生Future对象
        for (int i = 0; i < 10; i++) {
            results.add(exec.submit(new TaskWithResult(i)));//必须使用ExectorService.submit()方法调用
        }
        for (Future<String> fs :
                results) {
            try {
                System.out.println(fs.get()); //get()方法获取返回的结果,
            } catch (InterruptedException e) {
                System.out.println(e);
                return; 
            } catch (ExecutionException e) {
                System.out.println(e);
            }finally {
                exec.shutdown(); //关闭
            }
        }
    }
}
  • 可以使用Futrue对象的isDone()方法来查询Futrue是否已完成
  • 也可以直接调用get(),get()方法会等到结果就绪后调用

休眠

Thread.sleep();
Time.MILLISSECONDS.sleep(100)
//从运行态到阻塞态
  • sleep()的调用可以抛出异常,由于异常不能跨线程传给main,所以run()方法中捕获。

优先级

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimplePriorities implements Runnable{
    private int countDown = 5;
 private volatile double d;
 private int priority;
 public SimplePriorities(int priority) {
        this.priority = priority;
 }
    public String toString(){
        return Thread.currentThread()+"优先级:"+priority + "计数" + ":"+countDown;
 }
    @Override
     public void run() {
            Thread.currentThread().setPriority(priority);
            while (true) {
                for (int i = 0; i < 100000; i++) {
                    d += (Math.PI + Math.E) / (double) i;
                    if (i%1000==0) Thread.yield();
                }
            System.out.println(this);
            if (--countDown==0) return;
            }
     }
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
        }
        exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
        exec.shutdown();
 }
}
  • 首先这个例子的结果和书上的差别很大,问题不明
  • 调度器倾向于让优先权高的线程先执行,但并不意味着优先权较低的线程得不到执行(不会引发死锁)
  • 可以在一个任务内部,调用Thread.currentThread()来获得驱动该任务的Thread对象
  • volatile变量不进行任何编译器优化
  • 在构造器里设置优先级没有任何好处,因为Executor在此刻还没有开始执行任务
  • JDK有十个优先级但多数操作系统不能映射的很好,只使用THREAD.MIN_PRIORITY MAX_PRIORITY NORM_PRIORITY比较好

让步

image.png

  • 当调用Thread.yield()时,我们建议具有相同优先级的其他线程可以运行,但只是建议。从运行态到就绪态

后台线程

image.png

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static jdk.nashorn.internal.objects.Global.print;
public class SimpleDaemon implements Runnable {
    @Override
    public void run() {
        try {
            while (true) {
                TimeUnit.MILLISECONDS.sleep(100);
                System.out.println(Thread.currentThread() + " " + this);
            }
        } catch (InterruptedException e) {
            print("sleep() interrupt");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread daemon = new Thread(new SimpleDaemon());
            daemon.setDaemon(true);
            daemon.start();
        }
        System.out.println("All daemons started");
        TimeUnit.MILLISECONDS.sleep(100);
 }
}
  • 后台线程是在后台提供一些通用服务的线程,不属于不可或缺的一部分,其他线程都执行结束后会同时杀死所有的后台进程
  • 这里显式的创建了线程,以方便设置后台属性。还可以通过编写定制的ThreadFactory定义由Excecutor创建的线程的属性(后台、优先级、名称)
  • 可以调用isDaemon来确定是否为后台线程,后台线程创建的任何线程将自动被设置为后台线程
//实现线程工厂,设置属性
class DaemonThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}
//创建自己的线程
public class DaemonFromFactory implements Runnable{
    @Override
    public void run() {
        try {
            while (true) {
                TimeUnit.MILLISECONDS.sleep(100);
                System.out.println(Thread.currentThread()+" "+this);
            }  
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //将线程工厂传给线程池构造
        ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory());
        for (int i = 0; i < 10; i++) {
            //线程池将线程工厂的特性添加到自己的线程上运行
            exec.execute(new DaemonFromFactory());
        }
        System.out.println("All daemon started");
        TimeUnit.MILLISECONDS.sleep(100);
 }
}

贤魚
20 声望1 粉丝

如露亦如电


« 上一篇
阅读记录
下一篇 »
Java 线程(三)