多线程
程序 进程 线程
程序:完成特定的任务,用某种语言编写的一组指令的集合。一段静态代码,静态对象。
进程:正在运行的一个程序。有自身产生,存在和消逝。如运行中的qq。系统会给每个运行的进程分配内存空间。
线程:程序内部的执行路径。
⚪并发 和 并行
⭕并发:同一个时刻,多个任务交替执行的操作。造成一种 ” 貌似同时”的错觉 简单 来说 就是单核cpu实现的多任务就是并发。 人 同时打电话 同时开车 就是 并发的。 比如 你说话的时候打字 就很可能忙不过来。
⭕并行:同一个时刻,多任务真正的同时执行。 多核 cpu可以实现。、
⭕并发和并行 可能同时存在 电脑开了太多程序的情况。
并行:多个人同时做不同的事情。
并发:多个人同时做一件事请。
线程 是由 线程创建的 是进程的一个实体。
一个进程可以有多个线程。
例如 : 迅雷 使用的时候下载多个任务 代表 该进程的多个线程。
线程的创建和使用
创建线程的两种方式
⭕1、继承 Thread类 重写run方法。
⭕2、实现Runable接口,重写run方法。
测试一下:
public class Theard01 {
public static void main(String[] args) throws InterruptedException {
//创建一个Cat 对象,可以当作线程使用
System.out.println(Thread.currentThread().getName()); //main 线程
Cat cat = new Cat(); // Cat 类 继承了 Theard
cat.start();//开启一个新的线程 Thread - 01。
/*
* 主线程启动一个子线程时,主线程不会阻塞,会继续执行。 两个sleep 并行操作了属于是
* */
for (int i = 0; i < 10; i++) {
System.out.println("主线程执行中" + i);
Thread.sleep(1000);
}
}
}
class Cat extends Thread{
@Override
public void run() {
//该线程每隔1秒 输出一个喵喵喵
int times = 0;
while (true){
System.out.println("喵喵!我是小猫咪" + times + "字线程执行中" + Thread.currentThread().getName());
try {
Thread.sleep(1000); times ++;
if (times == 60) {
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
多线程机制
线程的创建和使用
JCONSOLE 线程监视
线程全部死亡 无法连接改 管理控制台
package day01;
public class Theard01 {
public static void main(String[] args) throws InterruptedException {
//创建一个Cat 对象,可以当作线程使用
System.out.println(Thread.currentThread().getName()); //main 线程
Cat cat = new Cat(); // Cat 类 继承了 Theard
cat.start();//开启一个新的线程 Thread - 01。
/*
* 主线程启动一个子线程时,主线程不会阻塞,会继续执行。 两个sleep 并行操作了属于是
* */
for (int i = 0; i < 10; i++) {
System.out.println("主线程执行中" + i);
Thread.sleep(1000);
}
}
}
class Cat extends Thread{
@Override
public void run() {
//该线程每隔1秒 输出一个喵喵喵
int times = 0;
while (true){
System.out.println("喵喵!我是小猫咪" + times + "字线程执行中" + Thread.currentThread().getName());
try {
Thread.sleep(1000); times ++;
if (times == 60) {
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//这里main线程运行了 10次 之后 main 线程会从控制台消失 也就是死掉。 从jconsole中可以看到。
//当 仅有的Theard-01 死掉之后 这个进程 也就会结束 卡
//也就是说明 只要存在子线程 运作 这个进程就不会结束。
第二种创建方式
public class Theard02 implements Runnable {
public static void main(String[] args) {
Theard02 theard02 = new Theard02();
Thread thread = new Thread(theard02);
thread.start();
// Runnable s = null;
// s.run();
}
@Override
public void run() {
System.out.println("sb" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
为什么要调用start 方法 而不是run方法
如果调用 run 方法 相当于从main 线程直接调用
System.out.println("喵喵!我是小猫咪" + times + "字线程执行中" + Thread.currentThread().getName()); 这里的语句线程名字则输出为 main线程。
这里就相当于一个串行化的操作 这里的程序就相当于一个串行化的过程。
start 静态方法 才是真正的 启动线程。
//调用start 方法后 start 会调用 start0() 方法 而start0() 方法会将线程变为看运行的状态,具体什么时候执行取决于你的cpu。
//更深详解 有待学习。
模拟Theard类
//模拟多线程运行Theard类
class TheardPox implements Runnable{
private Runnable target;
@Override
public void run() {
if (target != null){
target.run();//接口引用调用自己的方法 如果子类重写了该方法 就会执行 但他本身是是空的 因为接口里的方法都是抽象方法 当然除了的default方法
//不为空 说明指向了一个已经实现的对象。
}
}
public TheardPox(Runnable target) {
this.target = target;
}
public void start(){
start0();
}
public void start0(){
run();//start0() 才是线程的真正启动方法。
}
}
//Runnable 通过start方法动态绑定 Theard 类的run方法。 (代理模式 有时间看)
day03
线程的通知和退出
测试代码
package day03;
public class Quit {
public static void main(String[] args) throws InterruptedException {
t t = new t();t.start();
Thread.sleep(10 * 1000);
t.setLoop(false);
}
}
class t extends Thread{
private boolean loop = true;
//希望main线程控制他 必须让线程可以修改loop
//让 t 退出run方法 终止他的线程
public void setLoop(boolean loop) {
this.loop = loop;
}
@Override
public void run() {
int count = 0;
//通知退出他
while (loop){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t 运行中---" + (++count));
}
}
}
//主线程睡十秒通知 它 退出