方式一:继承Thread类重写run方法
public class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName()+"i am is thread!!!!"); } }
方式二:实现Runnable接口实现run方法
public class MyRunnable implements Runnable{ @Override public void run() { try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"i am myrunnable!!!"); } }
方式三:通过线程池的方式实现
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { String str = Thread.currentThread().getName()+":hello world!!"; return str; } }
测试
import org.junit.Test; import com.entity.MyCallable; import com.entity.MyRunnable; import com.entity.MyThread; public class ThreadDemo { @Test public void runnableTest() { Thread thread = new Thread(new MyRunnable()); thread.start(); } @Test public void threadTest() { Thread thread = new MyThread(); thread.start(); } @Test public void callableTest() throws InterruptedException, ExecutionException { ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(new MyRunnable()); Future<String> future = executorService.submit(new MyCallable()); System.out.println(future.get()); } }
总结:
***实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
***启动线程时时使用start方法,不能直接调用Run方法,直接调用Run方法和普通类的方法没有区别
**Runnable和Callable的区别
不同点:
- 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
- Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;
注意点:
- Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!