0
点赞
收藏
分享

微信扫一扫

了解并发编程(一)

Mezereon 2021-09-21 阅读 43
日记本

什么是线程

并发与并行

java 中实现线程的方式

继承 Thread 类,实现 run() 方法
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("这是创新的新线程,"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // 创建线程类
        MyThread thread = new MyThread();
        thread.start(); // 启动一个创建的线程
        System.out.println("这是主线程 main,"+Thread.currentThread().getName());
    }
}
实现 Runnable 接口
public class MyRunable implements Runnable{

    @Override
    public void run() {
        System.out.println("这是创新的新线程,"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Runnable runable = new MyRunable();
        Thread t1 = new Thread(runable);
        t1.start(); // 启动线程
        Thread t2 = new Thread(runable);
        t2.start(); // 启动线程

        /**
         * java 8 中 Runable 接口被标注为函数式接口,
         * @FunctionaInterface 修饰,可
         * 以使用 Lombok 表达式创建对象
         */
        Runnable able = () -> {
            System.out.println("使用 java 8 Lombok 表达式创建线程,"+Thread.currentThread().getName());
        };
        Thread t3 = new Thread(able);
        t3.start(); // 启动线程
        System.out.println("这是主线程 main,"+Thread.currentThread().getName());
    }
}
通过 Callable 和 Future 接口创建线程
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        // 休眠两秒
        Thread.sleep(2000);
        System.out.println("实现 Callable 接口 创建线程");
        return "SUCCESS";
    }

    public static void main(String[] args) throws Exception {
        Callable callable = new MyCallable();
        /**
         * java5 提供了 Future 接口来代表 Callable 接口里的 call() 方法的返回值
         * 并为 Future 提供了一个 FutureTask 实现类,该类实现了 Future 接口,并
         * 是实现了 Runnable 接口,所以 FutureTask 可以做为 Thread 类的 target
         * 同时也解决了 Callable 对象不能作为 Thread 类的 target 这一问题
         */
        FutureTask<String> task = new FutureTask<String>(callable);
        Thread t1 = new Thread(task,"call");
        t1.start();

        // 获取返回值
        String result = task.get();
        System.out.println("返回值:"+result);
        /**
         * 使用 lambda 表达式创建
         */
        FutureTask<Integer> task2 = new FutureTask<Integer>(() -> {
            System.out.println("100 分");
            return 100;
        });
        Thread t2 = new Thread(task2,"task2");
        t2.start();
        // Future 接口 get() 方法获取返回值 会阻塞线程,知道拿到返回值 其他线程才可以运行
        Integer resu = task2.get();
        System.out.println("返回值:"+resu);

        // 使用线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Callable<String> myCallable = new MyCallable();
        // 返回 Future 实例
        Future<String> submit = executorService.submit(myCallable);
        // 获取返回值,会阻塞线程
        String result3 = submit.get();
        System.out.println(result3);
        System.out.println("main 线程");
    }
}

线程的生命周期

java 的线程状态 6 中
线程的启动
线程的终止
public class MyInterrupt implements Runnable {

    private int i = 1;

    @Override
    public void run() {
        /**
         * Thread.currentThread().isInterrupted()
         * 返回会一个中段标记,默认为 false
         */
        while (!Thread.currentThread().isInterrupted()){
            System.out.println(Thread.currentThread().getName()+"="+i++);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = new MyInterrupt();
        Thread t1 = new Thread(runnable,"t1");
        Thread t2 = new Thread(runnable,"t2");
        t1.start();  // 启动线程
        t2.start();
        Thread.sleep(2000);
        /**
         * 设置中断标记 interrupt = true
         * 他会在当前线程最有一次执行完后通过判断中断标记,结束线程的执行
         */
        t1.interrupt();
    }
}

上述代码的 t1.interrupt() 只会让 t1 线程中断,而 t2 线程不会

public class MyInterrupt2 implements Runnable {

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){
                // 睡眠 200 秒
            try {
                TimeUnit.SECONDS.sleep(200);
            } catch (InterruptedException e) {
                /**
                 * InterruptedException 触发了线程的复位,线程不会终止即
                 * Thread.currentThread().isInterrupted() 返回 初始值 false
                 */
                e.printStackTrace();

                // 有人触发中断通知,在这里做处理

                // 继续中断,线程会停止
                Thread.currentThread().interrupt();
            }
        }

        /**
         * 如果没有改变中段标记为 true
         * 正常情况下是 200 秒之后才会执行
         */
        System.out.println("processor end");
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = new MyInterrupt2();
        Thread t1 = new Thread(runnable,"t1");
        t1.start(); // 启动线程

        // 为了让 t1 线程充分运行 执行到 run() 方法内
        Thread.sleep(1000);

        /**
         * 发送中断通知 设置中段标记为 true
         */
        t1.interrupt();
    }
}

上述代码可以让一个正在阻塞的线程是否中断,会抛出一个InterruptedException 异常, InterruptedException 会复位中断标记,不会中断线程,而在 catch 中可以决定如何处理这个中断请求,很明显这个处理中断请求的决定方是在当前线程。


举报

相关推荐

0 条评论