-
线程简介
任务,进程,线程,多线程
-
进程:程序是指令和数据的集合,其本身没有任何运行的含义,是一个静态的概念,当程序载入内存开始运行,这是程序的执行过程就是一个进程,它是一个动态的概念,是系统分配资源的单位
-
通常一个进程中会包含有若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义,线程是CPU调度和执行的单位。
-
注意:很多多线程是模拟出来的,其本身并不是多个任务同时在执行,真正的多线程,是指有多个CPU即多核,如服务器,如果是模拟出来的多线程,在同一个时间点,CPU只能执行一个代码,因为切换速度很快,所以有了同时执行的错觉。
Thread类(不建议使用)
-
第一种实现多线程方法,通过自定义一个线程类继承Thread类
-
public class Thread extends Object implements Runnable
static int
MAX_PRIORITY
线程可以拥有的最大优先级。static int
MIN_PRIORITY
线程可以拥有的最小优先级。static int
NORM_PRIORITY
分配给线程的默认优先级。 -
继承之后第一步重写run方法。
package com.thread.demo;
public class Demo1 extends Thread{ // 继承Thread类
/*
* 创建多线程第一种方式:继承Thread类重写 run方法,调用start方法开启线程
* 注意:线程开启,不一定立即执行,由CPU调度执行
* 线程之间是交替执行,谁执行看CPU的调度,无法认为干预
* */
@Override
public void run() {
for (int i = 0; i <1000 ; i++) { // 子线程
System.out.println("子线程---->"+i);
}
}
public static void main(String[] args) {
// main 主线程
Demo1 demo1 = new Demo1();
demo1.start();
for (int i = 0; i <1000 ; i++) {
System.out.println("主线程--->"+i);
}
}
}
Runnable接口
-
第二种实现方式,通过继承实现Runnable接口
-
然后重写run方法,通过new一个Thread对象来作为代理开启线程
package com.thread.demo;
public class Demo2 implements Runnable { // 实现了Runnable接口,
// 通过new Thread类的一个构造器将对象传入调用start方法开启线程
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("子线程 -------->" + i);
}
}
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
new Thread(demo2).start(); // 创建一个线程对象作为代理,开启子线程
for (int i = 0; i < 1000; i++) {
System.out.println("主线程 ------->" + i);
}
}
}
- 多线程模拟练习案例——龟兔赛跑
package com.thread.demo;
public class Demo4 implements Runnable {
public static void main(String[] args) {
Demo4 demo4 = new Demo4();
new Thread(demo4, "兔子").start();
new Thread(demo4, "乌龟").start();
/*
* 成绩:
* 1.游戏结束,胜利者是乌龟;兔子跑了:4866米
* 2.游戏结束,胜利者是乌龟;兔子跑了:7050米
* 3.游戏结束,胜利者是乌龟;兔子跑了:7521米
* 4.游戏结束,胜利者是乌龟;兔子跑了:6346米
* 5.游戏结束,胜利者是乌龟;兔子跑了:7349米
*
* */
}
private static String winner;
@Override
public void run() {
int flag = 1;
for (int i = 0; i <= 10000; i++) {
if (Thread.currentThread().getName().equals("兔子") && flag == 1) { // 模拟兔子睡觉
flag = 0;
try {
Thread.sleep(50); // 睡眠 0.05s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "已经跑了" + i + "米");
if (gameOver(i)) {
break;
}
}
}
private boolean gameOver(int i) {
if (winner != null) {
return true;
} else {
if (i >= 10000) {
winner = Thread.currentThread().getName();
System.out.println("游戏结束,胜利者是" + Thread.currentThread().getName());
}
}
return false;
}
}
Callable接口(了解)
- 实现callable接口,需要返回值类型
- 重写call方法,需要抛出异常
- ExecutorService executorService = Executors.newFixedThreadPool(3);//创建服务
- Future t1r = executorService.submit(t1);// 提交执行
- Boolean r1 = t1r.get();// 获取结果
- executorService.shutdownNow();// 关闭服务
package com.thread.demo;
import java.util.concurrent.*;
public class Demo5 implements Callable<Boolean> {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);//创建服务
Demo5 t1 = new Demo5();
Demo5 t2 = new Demo5();
Demo5 t3 = new Demo5();
// 提交执行
Future<Boolean> t1r = executorService.submit(t1);
Future<Boolean> t2r = executorService.submit(t2);
Future<Boolean> t3r = executorService.submit(t3);
// 获取结果
Boolean r1 = t1r.get();
Boolean r2 = t2r.get();
Boolean r3 = t3r.get();
// 关闭服务
executorService.shutdownNow();
}
@Override
public Boolean call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "子线程执行 --- >" + i);
}
return true;
}
}