美文网首页Java 杂谈
面试-实现多线程的方式

面试-实现多线程的方式

作者: 尹吉欢 | 来源:发表于2018-05-03 18:14 被阅读20次

    Java中实现多线程的方式有下面三种:

    1. 继承Thread类,重写run方法
    package fs;
    
    public class ThreadTest {
        public static void main(String[] args) {
            new MyThread().start();
        }
    }
    
    class MyThread extends Thread {
        
        @Override
        public void run() {
            System.out.println("我是一个线程,我叫:"+Thread.currentThread().getName());
        }
        
    }
    
    1. 实现Runnable接口,重写run方法
    package fs;
    
    public class ThreadTest {
        public static void main(String[] args) {
            new Thread(new MyRunnable()).start();
        }
    }
    
    class MyRunnable implements Runnable {
        
        @Override
        public void run() {
            System.out.println("我是一个线程,我叫:"+Thread.currentThread().getName());
        }
        
    }
    
    1. 通过Callable和FutureTask创建线程(最终还是Thread启动)
    package fs;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            MyCallable call = new MyCallable();
            FutureTask<String> task = new FutureTask<String>(call);
            new Thread(task).start();
            String result = task.get();
            System.out.println(result);
        }
    }
    
    class MyCallable implements Callable<String> {
        
        @Override
        public String call() throws Exception {
            return "Hello";
        }
        
    }
    

    上面的三种方式的区别在哪呢?

    • 实现方式不同
      第一种是继承的方式,第二种和第三种都是实现接口的方式

    • 返回值
      第一种和第二种有一个共同的特点就是没有返回值,而第三种是有返回值的

    • 扩展性
      在Java中我们都知道类只能单继承,如果我们自己创建的线程类是通过继承Thread类的方法来实现的,那么这个自定义类就不能再去扩展其他的类,也就是说不能再去实现更加复杂的功能。
      如果我们用实现Runnable接口的方式来创建线程类,这样就可以避免Java单继承所带来的局限性,通过接口多实现的特性进行扩展。

    • 资源共享/不共享
      继承的方式相当于一个线程只能干一件事情,接口实现可以多个多个线程干同一件事情

    下面通过一段简单的代码来进行讲解

    定义一个售票窗口类

    class TicketWindow extends Thread {
        int count = 100;
       
        @Override
        public void run() {
            System.out.println("窗口:"+Thread.currentThread().getName() + ":卖票啦" + count--);
        }
        
    }
    
    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            
            for (int i = 0; i < 5; i++) {
                TicketWindow t = new TicketWindow();
                t.start();
            }
        }
    }
    
    

    执行结果如下:

    窗口:Thread-1:卖票啦100
    窗口:Thread-0:卖票啦100
    窗口:Thread-2:卖票啦100
    窗口:Thread-3:卖票啦100
    窗口:Thread-4:卖票啦100
    

    每个线程都有自己的票总量,处理的都是自己的票,就是说每个窗口各自卖各自的票,这就是继承实现线程的特点,一个线程处理一件事情

    下面来看接口实现方式的代码

    class TicketWindow2 implements Runnable {
        int count = 100;
       
        @Override
        public void run() {
            System.out.println("窗口2:"+Thread.currentThread().getName() + ":卖票啦" + count--);
        }
        
    }
    
    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            TicketWindow2 t2 = new TicketWindow2(); 
            for (int i = 0; i < 5; i++) {
                new Thread(t2).start();
            }
        }
    }
    

    执行结果如下:

    窗口2:Thread-0:卖票啦100
    窗口2:Thread-3:卖票啦97
    窗口2:Thread-1:卖票啦99
    窗口2:Thread-2:卖票啦98
    窗口2:Thread-4:卖票啦96
    

    总共5个窗口也就是5个线程,执行的业务逻辑是相同的,相当于卖的是共享的票,我卖完了,你那边就不能卖了,实际上也是这样的,我们在12306买票就是这个逻辑,当然这边没有考虑到并发下票数超卖的情况。接口实现的方式可以让多个线程做同一件事情。

    更多技术分享请关注微信公众号:猿天地

    image.png

    相关文章

      网友评论

        本文标题:面试-实现多线程的方式

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