美文网首页
多线程线程——基础API

多线程线程——基础API

作者: 我不懂我不懂a | 来源:发表于2018-10-16 23:42 被阅读0次

    线程的创建

    创建线程有三种方式 thread,runnable,callable。

    1. 继承Thread类
    public class Test1 extends Thread{
        public static void main(String[] args) {
              Test1 test = new Test1();
              test.start();
        }
    
        @Override
        public void run(){
            //do something
        }
    }
    
    
    1. 实现Runnable接口
    public class Test2 implements Runnable {
    
        public static void main(String[] args) {
            Thread t1 = new Thread(new Test2());
            t1.start();
        }
    
        @Override
        public void run() {
            //do something
        }
    }
    
    1. 实现Callable接口
    public class Test3 implements Callable<Integer> {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            FutureTask<Integer> task = new FutureTask<Integer>(new Test3());
            new Thread(task).start();
    
            Integer result = task.get();
            System.out.println(result);
    
        }
    
        @Override
        public Integer call() throws Exception {
            //dosomething
            return 0;
        }
    }
    

    Callable是泛型接口,泛型中的类型正是调用call返回的类型。

    为什么使用Runnable而不是Thread
    答:

    1. 使用类继承Thread 不适合资源共享,
    2. 避免Java中单继承的限制
    3. 增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

    Runnable和Callable的区别
    答: Callable接口支持返回执行结果,Runnable不行。Callable接口的call()可以抛出异常V call() throws Exception; Runnable的run()只能内部捕获处理。

    run() 和 start()的区别
    答:由代码可以看到,run方法只是调用了target的run方法,还是在主线程中运行并未开启新的线程。而start()调用后,启动了新的线程。

    public
    class Thread implements Runnable {
        /* What will be run. */
        private Runnable target;
    
        @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }
    }
    

    线程的中断

    Thread# void interrupt 向线程发送中断请求,将中断flag置为true
    Thread# static boolean interrputed 测试线程是否为中断状态,重置中断flag为false
    Thread# isInterrputed 测试线程是否为中断状态,不会重置中断flag

    正确的使用interrupt终止线程的姿势

        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("...");
                Thread.currentThread().interrupt();
            }
        }
    

    wait()和notify()/notifyAll()

    wait和notify/notifyAll都是Object类的方法
    一个线程调用了object.wait( )后,这个线程就会进入该共享资源的等待队列,释放共享资源的锁。
    调用了object.notify( )后,会随机唤醒该资源的等待队列中随机一个线程(唤醒后线程并不能立即进入可运行状态(Runnable),而是进入阻塞状态(Blocked)等待获得锁)


    image.png image.png

    wait 和notify/notifyAll都需要在synchronized语句中才能执行。

    注意:IllegalMonitorStateException
    synchronized锁住的对象应该和调用wait与notify一样。

    /**
     * wait 和 notify/notifyAll的demo
     * 生产者消费者模型
     * Created by tjc on 2018-10-16.
     */
    public class Test5 {
    
        int count = 0;
    
        public static void main(String[] args) {
            Test5 test5 = new Test5();
    
            new Thread(new Product(test5)).start();
            new Thread(new Customer(test5)).start();
        }
    
    }
    
    class Product implements Runnable {
    
        Test5 test5 = null;
    
        Product(Test5 test5){
            this.test5 = test5;
        }
    
        @Override
        public void run() {
            synchronized (test5) {
                while (true) {
                    while (test5.count >= 5) {
                        try {
                            test5.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    test5.count++;
                    if(test5.count>=5) test5.notifyAll();
    
                    System.out.println(test5.count);
                }
            }
        }
    }
    
    class Customer implements Runnable {
    
        Test5 test5 = null;
    
        Customer(Test5 test5){
            this.test5 = test5;
        }
        @Override
        public void run() {
            synchronized (test5) {
                while (true) {
                    while (test5.count <= 0) {
                        try {
                            test5.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    test5.count--;
                    if(test5.count<=0) test5.notifyAll();
                    System.out.println(test5.count);
                }
            }
        }
    }
    

    注意:wait通常和while一起使用

    wait和sleep的区别
    答:wait 会释放锁,sleep不会

    yield() 和 join()

    yield让优先级更高的线程执行
    join让调用线程先执行

    相关文章

      网友评论

          本文标题:多线程线程——基础API

          本文链接:https://www.haomeiwen.com/subject/vznkzftx.html