进程和线程的区别:
进程是重量级的任务,需要分配给它们独立的地址空间。进程间通信是昂贵和受限的。进程间的转换也是很需要花费的。
另一方面,线程是轻量级的选手。它们共享地址空间并且共享同一个进程。线程间通信是便宜的,线程间的转换也是低成本的。
线程的生命周期
一个线程从创建到消亡的过程。线程的生命周期分为四个状态
1、创建状态
2、可运行状态
3、不可运行状态
4、消亡状态
线程的状态转换图
Java创建线程的三种方式: 1 继承Thread, 2.实现Runnable接口 3、实现Callable接口
一、Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别
<一>. java中实现线程的方式有Thread和Runnable
Thread:
public class Thread1 extends Thread{ @Override public void run() { System.out.println("extend thread"); } }
Runnable:
public class ThreadRunable implements Runnable{ public void run() { System.out.println("runbale interfance"); } }
使用
public static void main(String[] args) { new Thread1().start(); new Thread(new ThreadRunable()).start(); }
<二>.Thread和Runnable区别
1.在程序开发中使用多线程实现Runnable接口为主。 Runnable避免继承的局限,一个类可以继承多个接口
2. 适合于资源的共享
如下面的例子
public class TicketThread extends Thread{ private int ticketnum = 10; @Override public void run() { for(int i=0; i<20;i++){ if (this.ticketnum > 0) { ticketnum--; System.out.println("总共10张,卖掉1张,剩余" + ticketnum); } } } }
使用三个线程
public static void main(String[] args) { TicketThread tt1 = new TicketThread(); TicketThread tt2 = new TicketThread(); TicketThread tt3 = new TicketThread(); tt1.start(); tt2.start(); tt3.start(); }
实际上是卖掉了30张车票
而使用Runnable,如下面的例子
public class TicketRunnableThread implements Runnable{ private int ticketnum = 10; public void run() { for(int i=0; i<20;i++){ if (this.ticketnum > 0) { ticketnum--; System.out.println("总共10张,卖掉1张,剩余" + ticketnum); } } } }
使用三个线程调用
public static void main(String[] args) { TicketRunnableThread trt1 = new TicketRunnableThread(); new Thread(trt1).start(); new Thread(trt1).start(); new Thread(trt1).start(); }
因为TicketRunnableThread是New了一次,使用的是同一个TicketRunnableThread,可以达到资源的共享。最终只卖出10张车票。
3.效率对比
public static void main(String[] args) { long l1 = System.currentTimeMillis(); for(int i = 0;i<100000;i++){ Thread t = new Thread(); } long l2 = System.currentTimeMillis(); for(int i = 0;i<100000;i++){ Runnable r = new Runnable() { public void run() { } }; } long l3 = System.currentTimeMillis(); System.out.println(l2 -l1); System.out.println(l3 -l2); }
在PC上的结果
119 5
所以在使用Java线程池的时候,可以节约很多的创建时间
二、线程池
public class MyCallable implements Callable<Object> { private String taskNum; MyCallable(String taskNum){ this.taskNum = taskNum; } @Override public Object call() throws Exception { System.out.println(">>>" + taskNum + "任务启动"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任务终止"); return taskNum +"任务返回运行结果,当前任务执行时间[" + time + "]毫秒"; } public static void main(String[] args) throws ExecutionException, InterruptedException { int taskSize = 5; //创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); //创建多个有返回值的任务 List<Future> list = new ArrayList<>(); for(int i = 0; i< taskSize; i++){ Callable c = new MyCallable(i+ " "); //执行任务并获取Future对象 Future f = pool.submit(c); list.add(f); } pool.shutdown(); for(Future f : list){ //从Future对象获取任务的返回值 System.out.println(">>>" + f.get().toString()); } } }