一.java中线程实现几种实现方式 在Java中实现多线程一共有四种方式: (1)继承Thread类 (2)实现Runable接口 (3)实现Callable接口 (4)线程池 1.继承java.lang.Thread,重写run方法,启动线程,调用start()方法> 2.实现java.lang.Runnable接口,实现run方法 3.实现Callable接口(JDK8新特性) 该方法效率较低,因为在获取线程的执行结果的时候,当前线程受阻塞。但是可以拿到线程的返回结果。call()方法相当于run方法 call方法能向上抛出异常 Runnable是执行工作的独立任务,但是不返回任何值。如果我们希望任务完成之后有返回值,可以实现Callable接口。 FutureTask类提供了一个get()方法用来获取call()方法的返回值,但需要注意的是调用这个方法会导致程序阻塞,必须要等到线程结束后才会得到返回值。 public Object call() throws Exception { return object 类型; } 4,采用匿名内部类的方式
Thread thread=new Thread(new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
});
thread.start();
5.线程池 在Java中构建一个新的线程是需要一定的系统开销的,前面三种实现多线程的方法在线程执行完任务后就会将线程销毁, 那么是否可以在线程执行完任务后将线程保存下来,给下一个任务使用呢?答案是可以的,为了解决这个问题,线程池应运而生。 顾名思义,线程池就是用来存储线程的池子。线程池中包含许多准备运行的线程,我们只需要为线程池提供一个个任务, 线程池就会按照一定的规则去调用这些任务,当一个任务完成后,调用这个任务的线程不会死亡, 而是留在线程池中准备为下一个任务提供服务。 Executors类提供了许多静态工厂方法用来构造线程池,这里我介绍其中的三种: 1.newFixedThreadPool(int nThreads) 该方法用来构造一个固定大小的线程池,空闲的线程会一直保留着,如果提交的任务数多于空闲线程数,就会把未得到服务的任务放到队列中等待
public class MyFixedThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 调用 Runnable 任务
TestRunnable1 testRunnable1 = new TestRunnable1();
for (int i = 0; i < 5; i++) {
// 调用 Runnable 任务可以用以下两种方法,二者的区别在于前者没返回值,后者有返回值
//第一种方法
executorService.execute(testRunnable1);
//第二种方法
Future<?> submit = executorService.submit(testRunnable1);
}
// 调用 Callable 任务
TestCallable1 testCallable1 = new TestCallable1();
for (int i = 0; i < 5; i++) {
// 调用 Callable 任务只能用这一种方法
Future<Integer> submit = executorService.submit(testCallable1);
System.out.println("返回值:" + submit.get());
}
}
}
class TestRunnable1 implements Runnable {
@Override
public void run() {
System.out.println("我是 Runnable 任务,调用我的线程是:" + Thread.currentThread().getName());
}
}
class TestCallable1 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("我是 Callable 任务,调用我的线程是:" + Thread.currentThread().getName());
return 666;
}
}
2.newCachedThreadPool() 该方法构建的线程池会立即执行任务,如果当前存在空闲线程,则直接执行任务;如果当前不存在空闲线程,则创建一个新线程执行任务。在该线程池内空闲线程只会保留60秒
public class MyCachedThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
// 调用 Runnable 任务
TestRunnable2 testRunnable2 = new TestRunnable2();
for (int i = 0; i < 5; i++) {
// 调用 Runnable 任务可以用以下两种方法,二者的区别在于前者没返回值,后者有返回值
executorService.execute(testRunnable2);
Future<?> submit = executorService.submit(testRunnable2);
}
// 调用 Callable 任务
TestCallable2 testCallable2 = new TestCallable2();
for (int i = 0; i < 5; i++) {
// 调用 Callable 任务只能用这一种方法
Future<Integer> submit = executorService.submit(testCallable2);
System.out.println("返回值:" + submit.get());
}
}
}
class TestRunnable2 implements Runnable {
@Override
public void run() {
System.out.println("我是 Runnable 任务,调用我的线程是:" + Thread.currentThread().getName());
}
}
class TestCallable2 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("我是 Callable 任务,调用我的线程是:" + Thread.currentThread().getName());
return 666;
}
}
3.newSingleThreadExecutor() 该方法构建的线程池只存在一个线程,会顺序地执行所提交的任务。
public class MySingleThreadExecutor {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 调用 Runnable 任务
TestRunnable3 testRunnable3 = new TestRunnable3();
for (int i = 0; i < 5; i++) {
// 调用 Runnable 任务可以用以下两种方法,二者的区别在于前者没返回值,后者有返回值
executorService.execute(testRunnable3);
Future<?> submit = executorService.submit(testRunnable3);
}
// 调用 Callable 任务
TestCallable3 testCallable3 = new TestCallable3();
for (int i = 0; i < 5; i++) {
// 调用 Callable 任务只能用这一种方法
Future<Integer> submit = executorService.submit(testCallable3);
System.out.println("返回值:" + submit.get());
}
}
}
class TestRunnable3 implements Runnable
{
@Override
public void run() {
System.out.println("我是 Runnable 任务,调用我的线程是:" + Thread.currentThread().getName());
}
}
class TestCallable3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("我是 Callable 任务,调用我的线程是:" + Thread.currentThread().getName());
return 666;
}
}
标签:面试题,调用,##,submit,Callable,任务,Runnable,线程
From: https://blog.51cto.com/u_16243704/7354851