Java 的Runnable和Callable的区别

RunnableCallable的区别是,
(1)Callable规定的方法是call(),Runnable规定的方法是run().
(2)Callable
的任务执行后可返回值,而Runnable的任务是不能返回值得
(3)call方法可以抛出异常,run方法不可以
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

1.1使用Runnble接口 创建线程


public class RunnableTest implements Runnable {
    @Override
    public void run() {
        System.out.println("this thread name is:"+Thread.currentThread().getName());
    }
     
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
        RunnableTest r = new RunnableTest();
        Thread t = new Thread(r);
        t.start();
    }
}

或者使用匿名类实现:


		Thread thread =new Thread(new Runnable() {
			
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("匿名类实现线程");
			}

使用1.2 使用 Executors 创建线程

package com.asiainfo.proxydemo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadExecutorService {
	//设置线程的数量
	private  static int POOL_NUM=10;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
//		ExecutorService newFixedThreadPool = Executors.newCachedThreadPool();
//		ExecutorService newFixedThreadPool = Executors.newScheduledThreadPool(3);
//		ExecutorService newFixedThreadPool = Executors.newSingleThreadExecutor();
		ExecutorService newFixedThreadPool = Executors.newSingleThreadScheduledExecutor();
		for (int i = 0; i < POOL_NUM; i++) {
			RunnableImpl runnableImpl = new RunnableImpl("thread--"+i);
			newFixedThreadPool.execute(runnableImpl);
		}
		newFixedThreadPool.shutdown();
	}

}
class RunnableImpl implements Runnable{
	private String name;

	public RunnableImpl(String name) {
		super();
		// TODO Auto-generated constructor stub
		this.name=name;
	}

	public void run() {
		// TODO Auto-generated method stub
		System.out.println("hello ExecutorService"+name);
	}
	
}

2.1 使用Callable 创建线程

package com.asiainfo.proxydemo;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class ThreadCallable {
  /**
 * @param args
 */
public static void main(String[] args) {
	Tickets<java.lang.Object> tickets = new Tickets<Object>();
	FutureTask<java.lang.Object> futureTask = new FutureTask<Object>(tickets);
	Thread thread = new Thread(futureTask);
	System.out.println(Thread.currentThread().getName());
	thread.start();
}
}
class Tickets<Object> implements Callable<Object>{

	/* (non-Javadoc)
	 * @see java.util.concurrent.Callable#call()
	 */
	public Object call() throws Exception {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+"通过实现Callable接口通过FutureTask包装器来实现线程");
		return null;
	}
	
}

     2.2 使用 Executors 结合Callable 创建多线程

      在Java5之 后,任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。两者都可以被ExecutorService执行,但是 Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的 submit(Callable<T> task) 方法来执行,并且返回一个 <T> Future<T>,是表示任务等待完成的 Future.

  public interface Callable<V>返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。

  Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。

  Executors 类包含一些从其他普通形式转换成 Callable 类的实用方法。

  Callable中的call()方法类似Runnable的run()方法,就是前者有返回值,后者没有。

扫描二维码关注公众号,回复: 2324842 查看本文章

  当将一个Callable的对象传递给ExecutorService的submit方法,则该call方法自动在一个线程上执行,并且会返回执行结果Future对象。

  同样,将Runnable的对象传递给ExecutorService的submit方法,则该run方法自动在一个线程上执行,并且会返回执行结果Future对象,但是在该Future对象上调用get方法,将返回null.

package com.asiainfo.proxydemo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ThreadCallableDemo2 {
	public static void main(String[] args) {
		ExecutorService executorService = Executors.newCachedThreadPool();
		List<Future<String>> resultList = new ArrayList<Future<String>>();
		// 创建10个任务并执行
		for (int i = 0; i < 10; i++) {
			// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
			Future<String> future = executorService.submit(new TaskWithResult(i));
			// 将任务执行结果存储到List中
			resultList.add(future);
		}
		// 遍历任务的结果
		for (Future<String> fs : resultList) {
			try {
				System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			} finally {
				// 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
				executorService.shutdown();
			}
		}
	}
}

class TaskWithResult implements Callable<String> {
	private int id;

	public TaskWithResult(int id) {
		this.id = id;
	}
	public String call() throws Exception {
		System.out.println("call()方法被自动调用,干活!!!             " + Thread.currentThread().getName());
		// 一个模拟耗时的操作
		for (int i = 999999; i > 0; i--)
			;
		return "call()方法被自动调用,任务的结果是:" + id + "    " + Thread.currentThread().getName();
	}
}

参考:https://blog.csdn.net/w2393040183/article/details/52177572

http://murielily.blog.163.com/blog/static/134260649201131215237637/

猜你喜欢

转载自blog.csdn.net/jhon07/article/details/81147882