多线程(二十一)
多线程(二十一)
进程是一个独立的运行环境,而线程是在进程中执行的一个任务。他们本质的区别是是否单独占有内存地址空间和其他系统资源(如IO资源)。
实现多线程的几种方式
一、继承Thread类
package com.thread;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
public class TestThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程输出"+i);
}
}
public static void main(String[] args) {
//获取开始时间
Date date = new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println("开始时间为:"+dateFormat.format(date));
//多线程实现方式一:继承Thread类,重写run方法,使用start方法启动线程
TestThread1 testThread1 = new TestThread1();
testThread1.start();
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主程序输出"+i);
}
Date date2 = new Date();
SimpleDateFormat dateFormat2= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println("开始时间为:"+dateFormat2.format(date2));
}
}
使用Thread类实现多线程的流程是,继承Thread类,重写run方法,然后使用就行。
二、继承Runnable接口
package com.thread;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class TestThread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程输出"+i);
}
}
public static void main(String[] args) {
//获取开始时间
Date date = new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println("开始时间为:"+dateFormat.format(date));
//多线程实现方式二:继承Runnable接口,重写run方法,Thread代理启动线程
TestThread2 testThread2 = new TestThread2();
new Thread(testThread2).start();
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主程序输出"+i);
}
Date date2 = new Date();
SimpleDateFormat dateFormat2= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println("开始时间为:"+dateFormat2.format(date2));
}
}
使用Runnable接口与Thread类似,也是继承Runnable,然后重写run方法,通过Thread类的start方法启动线程。
三、使用Callable方式
package com.threademo.proandcum;
import java.util.concurrent.*;
public class PoolDemo {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
TestPool tp = new TestPool();
Future<Integer> result1 = service.submit(tp);
Future<Integer> result2 = service.submit(tp);
Future<Integer> result3 = service.submit(tp);
try {
System.out.println(result1.get());
System.out.println(result2.get());
System.out.println(result3.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
service.shutdown();
}
}
}
class TestPool implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("Call is running...");
return 100;
}
}
Call is running...
Call is running...
Call is running...
100
100
100
Process finished with exit code 0
使用Callable的方式启动线程,它与上面两种方式的区别是,它在执行完线程后会有一个返回值。