多线程学习总结笔记
何为多线程
我们对于自己而言,总希望自己的效率能高一些,同样对于计算机也不例外,我们即希望它能同时播放音乐又能编辑文档还能敲代码,这个想法就叫做并发,将并发完成的每件事就叫做线程。每一个线程独立完成自己的功能,和其他线程并发执行,这种模式就叫做多线程。
讲到线程就不得不说进程了,因为它们兄弟两谁也离不开谁,进程可以理解为软件正在运行的过程,所以它是系统分配和调度的独立单元,有其自己的内存空间和系统资源。
怎么实现多线程
首先程序能够并发执行的的基本套路是:
(1)创建进程,系统在创建一个进程时,必须为它分配其所必需的、除处理机以外的所有资源,如内存空间、I/O设备,以及建立相应的PCB;
(2)撤消进程,系统在撤消进程时,又必须先对其所占有的资源执行回收操作,然后再撤消PCB;
(3)进程切换,对进程进行上下文切换时,需要保留当前进程的CPU环境,设置新选中进程的CPU环境,因而须花费不少的处理机时间。
看着如此的麻烦就能想到要消耗多大的时间和空间开销,故引用多线程去简化这个过程,减少时间和空间开销,从而提高效率。
创建多线程有三种方法,当然常用的是前面两种:
• 继承Thread,重写run方法
• 实现Runnable接口,重写run方法
• 实现Callable接口,重写run方法
1.继承Thread,重写run方法
首先编写一个类 继承Thread 重写run方法 创造一条新执行路径
public class MyThread extends Thread {
/** run方法就是线程要执行的任务方法*/
public void run() {
//这里的代码 是一条新的执行路径
//这个执行路径的触发方式 不是调用run方法,而是通过thread对象的start()来启动任务
for(int i = 0;i<10;i++) {
System.out.println("锄禾日当午"+i);
}
}
}
然后在另外一个类里面调用它
public class Demo1 {
public static void main(String[] args) {
//Thread
MyThread m = new MyThread();
//开启一个新的任务 分支线程 并发
m.start();
for(int i = 0;i<10;i++) {
System.out.println("旱地禾下土"+i);
}
}
}
2.实现Runnable接口,重写run方法
实现Runnable接口,重写run方法
public class MyRunnable implements Runnable {
//重写run方法
public void run() {
//线程的任务
for(int i=0;i<10;i++) {
System.out.println("床前明月光"+i);
}
}
}
然后在另外一个类里面调用它
public class Demo2 {
public static void main(String[] args) {
//Runnable类
//创建一个任务对象
MyRunnable r = new MyRunnable();
//创建一个线程 并为其分配一个任务
Thread t = new Thread(r);
// 执行这个线程
t.start();
for(int i =0;i<10;i++) {
System.out.println("疑是地上霜"+i);
}
}
}
3.实现Callable接口,重写run方法
public class Demo {
//两个线程交替执行
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<Integer> c = new MyCallable();
FutureTask<Integer> task = new FutureTask<>(c);
new Thread(task).start();
//此处的意思是先暂停等返回值 此时副线程,没有等主线程
Integer j = task.get();
for(int i = 0;i<10;i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(i);
}
}
//实现Callable接口 并重载run方法
static class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
for(int i = 0;i<10;i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("副"+i);
}
return null;
}
}
Java实现多线程需要注意的细节
1.run()和start()方法区别:
• run():仅仅是封装被线程执行的代码,直接调用是普通方法
• start():首先启动了线程,然后再由jvm去调用该线程的run()方法。
2.jvm虚拟机的启动是单线程的还是多线程
• 是多线程的。不仅仅是启动main线程,还至少会启动垃圾回收线程的,不然谁帮你回收不用的内存
3.什么方式用的最多
一般是Runnable接口 ,理由如下:
• 可以避免java****中的单继承的限制
• 应该将并发运行任务和运行机制解耦,因此我们选择实现Runnable接口这种方式!
本文末尾关于多线程细节部分整理于3y大哥,原文处:https://github.com/ZhongFuCheng3y/3y