面试题-实现多线程的方式

面试题-实现多线程的方式

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

  • 继承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());
    }
}
  • 实现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());
    }
}
  • 经过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单继承所带来的局限性,经过接口多实现的特性进行扩展。并发

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

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

定义一个售票窗口类线程

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();
        }
    }
}

执行结果以下:code

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

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

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

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买票就是这个逻辑,固然这边没有考虑到并发下票数超卖的状况。接口实现的方式可让多个线程作同一件事情。

推荐相关阅读:

  • 《注解面试题-请了解下》

  • 《反射面试题-请了解下》
    更多技术分享请加我微信,我拉你进群进行交流:
    面试题-实现多线程的方式
相关文章
相关标签/搜索