基本线程机制

来源:互联网 发布:linux更改用户权限 编辑:程序博客网 时间:2024/06/03 19:58

基本线程机制

@(并发)[java, 并发, Thinking in Java]

  • 基本线程机制
  • 定义任务
  • Thread类
  • 使用Executor
  • 从任务中返回值实现Callable接口
  • 休眠
  • 优先级
  • 让步
  • 后台daemon线程
    • 1 设置后台标志
    • 2 定制ThreadFactory
  • 编码的变体
    • 1 直接继承Thread
    • 2 自管理的Runnable
    • 3 匿名内部类
  • 术语
  • 加入一个线程
  • 创建有响应的用户界面
  • 线程组 -不成功的尝试
  • 捕获异常

  1. 单个进程可以拥有多个并发执行的任务,其底层机制是切分CPU时间

1. 定义任务

  1. 实现Runnable接口并编写run()方法
  2. 线程调度器:Thread.yield():Java线程机制的一部分,可以将CPU从一个线程转移给另一个线程,但是是选择性

2. Thread类

Thread thread = new Thread(obj implements Runnable);
thread.start()方法为线程执行必须的初始化操作,然后调用run()方法。

3. 使用Executor

java.util.concurrent包的执行器(Executor)将管理Thread对象,执行任务。Executor允许管理异步任务的执行—-优选

ExecutorService executor = Executors.newCachedThreadPool();executor.execute(obj implement Runnable);executor.shutdown();//防止新任务提交给Executor

FixedThreadPool: 一次性预先执行代价高昂的线程分配,即限制线程的数量。
CachedThreadPool: 在程序执行过程中通常会创建与所需数量相同的线程,然后在回收旧线程时停止创建新线程
SingleThreadExecutor:线程数量为1的FixedThreadPool,会序列化所有提交给它的任务

4. 从任务中返回值–实现Callable接口

Callable接口是一种具有类型参数的泛型,它的类型参数表示的是从call()中返回的值,并且必须用ExecutorService.submit()调用。submit()方法会产生Future对象。

class MyClass implements Callable<String>{}ExecutorService executor = Executors.newCachedThreadPool();Future<String> result = executor.submit(new MyClass());

5. 休眠

Thread.sleep(10);TimeUnit.MILLISECONDS.sleep(10); //建议

6. 优先级

线程的优先级将该线程的重要性传递给调度器。调度器倾向于让优先权最高的线程执行。但优先级不会导致死锁。
优先级需要在run()方法的开头部分设定。
JDK有10个优先级,但是它与多数操作系统不能映射的很好,所以只建议使用MAX_PRIORITY, NORM_PRIORITY, MIN_PRIORITY三个等级

7. 让步

Thread.yield(): 暗示可以出让CPU给其它线程,但是没有任何机制会保证它将会被采纳。

8. 后台(daemon)线程

☞在后台提供通用服务的线程,并且这些线程并不属于程序中不可或缺的那部分。所以当所有非后台线程结束时,程序也就终止了,同时会杀死进程中所有的后台线程。

8.1 设置后台标志

//线程启动**之前**调用setDaemon()方法,才能将它设置为后台线程。Thread daemon = new Thread(obj implement Runnable);daemon.setDaemon(true);daemon.start();

8.2. 定制ThreadFactory

public class DaemonThreadFactory implements ThreadFactory{    public Thread newThread(Runnable r){        Thread t = new Thread(r);        t.setDaemon(true);        return t;    }}public static void main(String[] args){    ExecutorService executor = Executors.newCachedThreadPool(new DaemonThreadFactory());    executor.execute(obj implements Runnable);}

Daemon线程派生出的子线程默认也为Daemon

9. 编码的变体

9.1. 直接继承Thread

public class MyThread extends Thread{}

9.2. 自管理的Runnable

public class SelfManaged implement Runnable{    private Thread t = new Thread(this);    public SelfManaged(){        t.start();    }    public void run(){}}//该方法可能会访问到处于不稳定状态的对象。因为另一个任务可能会在构造器结束之前开始执行。

9.3. 匿名内部类

10. 术语

Thread类自身不执行任何操作,它只是驱动赋予它的任务

11. 加入一个线程

如果某个线程在另一个线程t上调用t.join(),此线程将被挂起,直到目标线程t结束才恢复(即t.isAlive()返回false)
join()方法可以带超时参数,这样如果目标线程在这段时间到期还没结束的话,join()方法返回。

12. 创建有响应的用户界面

13. 线程组 —-不成功的尝试

14. 捕获异常

问题:线程中不能捕获异常,一旦逃出任务的run()方法,就会向外传播到控制台。即使在main()方法中捕获也没用

package concurrency;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;/** * ${DESCRIPTION} * * @author cinhori * @version 1.0 * @since 2017-08-12 12:50 */public class CaptureUncaughtException {    public static void main(String[] args){        ExecutorService service = Executors.newCachedThreadPool(new HandlerThreadFactory());        service.execute(new ExceptionThread2());    }}class ExceptionThread2 implements Runnable{    @Override    public void run() {        Thread thread = Thread.currentThread();        System.out.println("run by " + thread.getName());        System.out.println("exceptionHandler: " + thread.getUncaughtExceptionHandler());        throw new RuntimeException();    }}class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{    @Override    public void uncaughtException(Thread t, Throwable e) {        System.out.println("caught " + e.toString());    }}class HandlerThreadFactory implements ThreadFactory{    @Override    public Thread newThread(Runnable r) {        System.out.println(this + " creating new Thread");        Thread thread = new Thread(r);        System.out.println("creating " + thread);        thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());        System.out.println("ExceptionHandler: " + thread.getUncaughtExceptionHandler());        return thread;    }}

设置默认的未处理捕获异常处理器:

public class SettingDefaultHandler{    public static void main(String[] args){        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());        ExecutorService service = Executors.newCachedThreadPool();        service.execute(new ExceptionThread());    }}
原创粉丝点击