進程和線程的區別:
進程是重量級的任務,需要分配給它們獨立的地址空間。進程間通信是昂貴和受限的。進程間的轉換也是很需要花費的。
另一方面,線程是輕量級的選手。它們共享地址空間並且共享同一個進程。線程間通信是便宜的,線程間的轉換也是低成本的。
線程的生命周期
一個線程從創建到消亡的過程。線程的生命周期分為四個狀態
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());
}
}
}
