学习总结-Thinking In Java Chapter concurrency(1)

学习总结

本篇是对学习【Java编程思想 第 21 章 并发-基本的线程机制】的学习总结。

标签: Java Thread

启动线程

实现Runnablejiek
继承Thread

使用Executor

//创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。   
ExecutorService executor1 = Executors.newCachedThreadPool();

//创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
ExecutorService executor2 = Executors.newFixedThreadPool(5);

//创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
ExecutorService executor3 = Executors.newSingleThreadExecutor();

单个的Executor被用来创建和管理系统中所有任务。
ExecutorService shutdown()方法的调用可以防止新任务被提交给这个Executor
SingleThreadExecutor被提交多个任务后,每个任务都会在下一个任务开始之前结束。

//在未来某个时间执行给定的命令。
executor.execute(new Fibonacci4("FixedThreadPool", i));

从任务中产生返回值

实现Callable接口,提供泛型参数,表示从call()方法中返回的值类型。

class TaskWithResult implements Callable<String> {

    private int id;

    public TaskWithResult(int id) {
        this.id = id;
    }

    @Override
    public String call() throws Exception {
        return "result with " + id;
    }
}

然后调用ExecutorServicesubmit(Callable<T> task) 方法。该方法提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。

利用Future的get()方法获取任务的返回值,该方法会一直阻塞,知道结果被算出,其重载方法get(long timeout, TimeUnit unit)表示如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。

休眠

Thread.sleep();
TimeUnit.MILLISECONDS.sleep();

让步

Thread.yield();
建议具有相同优先级的线程可以运行。

优先级

//用Thread.currentThread()来获得对驱动该任务的Thread对象的引用
Thread.currentThread().setPriority(priority);

可以用setPriority()getPriority()设置或获取当前线程的优先级。尽管Java有10个优先级,但它与多数操作系统都不能很好地映射。唯一可移植的方法是当调整优先级时,只是用MAX_PRIORITY,NORM_PRIORITY,MIN_PRIORITY三种级别。

后台线程

所谓后台线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说,只要后台线程存活,程序就不会终止。

// Must call before start()
daemon.setDaemon(true); 

必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。

如果一个线程是后台线程,那么它创建的任何线程都将被自动设置成后台线程。

多种形式创建线程

extends Thread + 在构造函数中启动线程

public class SimpleThread extends Thread {
  public SimpleThread() {
    start();
  }
}

implements Runnanle + 持有Thread对象 + 在构造函数中启动线程

public class SelfManaged implements Runnable {
    private Thread t = new Thread(this);
    public SelfManaged() { t.start(); }
} 

Inner Class extends Thread

Anonyous inner class + 持有Thread对象 + 在构造函数中启动线程

public InnerRunnable2(String name) {
    t = new Thread(new Runnable() {
      public void run() {
        try {
          while(true) {
            print(this);
            TimeUnit.MILLISECONDS.sleep(10);
          }
        } catch(InterruptedException e) {
          print("sleep() interrupted");
        }
      }
    }, name);
    t.start();
  }

Inner Class implements Runable + 持有Thread对象 + 在构造函数中启动线程

private class Inner implements Runnable {
    Thread t;
    Inner(String name) {
      t = new Thread(this, name);
      t.start();
    }
    public void run() {
      try {
        while(true) {
          print(this);
          if(--countDown == 0) return;
          TimeUnit.MILLISECONDS.sleep(10);
        }
      } catch(InterruptedException e) {
        print("sleep() interrupted");
      }
    }
  }

加入线程

Thread.join()

如果某个线程在另一个线程上调用另一个线程tt.join(),此线程将被挂起,知道目标线程t结束才恢复。

无法捕获的异常

由于线程的特殊性,使得你不能捕获从线程中逃逸的异常。
看个例子:

import java.util.concurrent.*;

class ExceptionThread implements Runnable {
  public void run() {
    throw new RuntimeException();
  }
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    exec.execute(new ExceptionThread());
  }
} 

public class NaiveExceptionHandling {
  public static void main(String[] args) {
    try {
      ExecutorService exec =
        Executors.newCachedThreadPool();
      //将发生异常
      exec.execute(new ExceptionThread());
      // 由于异常没有被捕获,这句话得以执行
      exec.shutdown();
    } catch(RuntimeException ue) {
      // 这句话不会被执行
      System.out.println("Exception has been handled!");
    }
  }
} 

解决之道:

Thread.setDefaultUncaughtExceptionHandlerJava SE 5的新接口,它允许你在每个Thread对象上都附着一个异常处理器,它会在线程因为未被捕获的异常而临近死亡的时候被调用。

class MyUncaughtExceptionHandler implements
Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
    System.out.println("caught " + e);
  }
}

当然你可以用ThreadFactory为每个生成的Thread附着上这样一个定制的Thread.setDefaultUncaughtExceptionHandler

更简单的方式是在Thread类中设置一个静态域,并将这个处理器设置为默认的未被捕获异常处理器。

Thread.setDefaultUncaughtExceptionHandler(
      new MyUncaughtExceptionHandler());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值