进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
① 顺序执行:即程序从上往下一步一步的执行
② 并发执行:指两个或多个事件在同一个时间段内执行
③ 并行执行:指两个或多个事件在同一时刻同时执行
继承Thread类后要重写Thread类的run()方法,然后调用start()方法开启线程
public class TestThread1 extends Thread{
public static void main(String[] args) {
EatThread eatThread = new EatThread();
DrinkThread drinkThread = new DrinkThread();
eatThread.start();
drinkThread.start();
}
}
class EatThread extends Thread{
@Override
public void run() {
System.out.println("开始吃饭?...\t" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束吃饭?...\t" + new Date());
}
}
class DrinkThread extends Thread {
@Override
public void run() {
System.out.println("开始喝酒?...\t" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束喝酒?...\t" + new Date());
}
}
此时的运行结果为:
当把主函数(即主线程)改为run()方法开启线程:
public class TestThread1 extends Thread{
public static void main(String[] args) {
EatThread eatThread = new EatThread();
DrinkThread drinkThread = new DrinkThread();
eatThread.run();
drinkThread.run();
}
}
此时的运行结果为:
造成区别的原因时:当使用start()方法开启线程时,各线程是并发执行的,当使用run()方法开启线程时,各线程是顺序执行的。
与继承Thread类方法类似,实现Runnable接口后要重写run()方法,然后使用Thread类来包装调用start()方法开启线程
public class TestThread2 implements Runnable{
@Override
public void run() {
System.out.println("开始吃饭?...\t" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束吃饭?...\t" + new Date());
}
public static void main(String[] args) {
TestThread2 t1 = new TestThread2();
new Thread(t1).start();
Thread thread = new Thread(t1); //对同一对象进行多线程从操作
thread.start();
}
}
注意:
new Thread(t1).start();
和
Thread thread = new Thread(t1);
thread.start();
这两种写法效果是一样的
第一种方法继承Thread类,Thread类也实现了Runnable接口
第二种方法实现Runnable接口,类似创建一个代理工具类
推荐使用实现Runnable接口的方法实现多线程,可以避免Java单线程的限制
线程开启不一定立即执行,由CPU调度执行
① 实现Callable接口,需要返回值类型
② 重写call()方法,需要抛出异常
③ 创建目标对象 : TestThread3 testThread3 = new TestThread3()
④ 创建执行服务 : ExecutorService ser = Executors.newFixedThreadPool(2)
⑤ 提交执行 : Future r1 = ser.submit(testThread3)
⑥ 获取结果 : boolean rst1 = r1.get();
⑦ 关闭服务 : ser.shutdownNow();
public class TestThread3 implements Callable<Boolean> {
//①实现Callable接口,需要返回值类型
private String name;
public TestThread3(String name){
this.name = name;
}
@Override
public Boolean call() throws Exception {
//②重写call()方法,需要抛出异常
if(name.equals("张三")){
System.out.println("欢迎"+name);
return true;
}
return false;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//③创建目标对象
TestThread3 t1 = new TestThread3("张三");
TestThread3 t2 = new TestThread3("李四");
//④创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(2);
//⑤提交执行
Future<Boolean> r1 = ser.submit(t1);
Future<Boolean> r2 = ser.submit(t2);
//⑥获取结果
boolean rst1 = r1.get();
boolean rst2 = r2.get();
System.out.println(rst1);
System.out.println(rst2);
//⑦关闭服务
ser.shutdownNow();
}
}
public class Race implements Runnable{
private static String winner;
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
// 模拟兔子休息
if(Thread.currentThread().getName().equals("兔子") && i%10==0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean flag = isGameOver(i);
// 如果比赛结束,终止程序
if (flag){
break;
}
// Thread.currentThread()获取当前线程
// Thread.currentThread().getName()获取当前线程名字
System.out.print(Thread.currentThread().getName()+"-->跑了"+i+"步"+"\t");
if(i%5==0)
System.out.println();
}
}
// 判断是否有胜利者
public boolean isGameOver(int step){
if (winner!=null){
return true;
}else{
if (step>=100){
winner = Thread.currentThread().getName();
System.out.println("winner is "+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
结果:
参考: https://blog.csdn.net/vbirdbest/article/details/81282163.