多线程详解 java Thread
1.线程的简介
1.任务,进程,线程,多线程
多任务:一个人在一段时间内看起看来向进行许多任务,但是其实真正大脑只在执行一个任务
多线程:
多分支和多线程
普通方法调用一个函数,其实是在顺序执行,没有办法同时执行,而多线程就可以
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y7zNveJB-1651654409852)(${images}/image-20210514104314760.png)]
进程:在操作系统中运行中的程序就是进程,比如qq,播放器,
一个进程可以有多个线程,如视频中同时听声音,看图像,看弹幕,等等
2.Process和Thread
Process(进程)
Thread(线程)
- 说起进程,就必须说到程序。程序是指令和数据的有序集合,本身没有任何运行的含义,是一个静态的概念
- 而进程,是动态的,是系统分配资源的单位
- 通常一个进程包含若干个线程,线程是cpu调度和执行的单位
注意!很多多线程都是模拟出来的,真正的多线程应该是多个cpu执行多个任务,即多核
模拟出来的cpu,在同一时间,cpu只能执行一个代码,但是切换的很快,所以有了同时执行的错觉
main()主线程,gc线程(垃圾回收)
本章核心
- 线程就是独立的执行路径
- 在程序执行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程
- main()称之为主线程,位系统的入口,用于执行整个程序
- 在一个进程中如果开辟了多个线程,那么线程的运行有调度器安排调度,
- 对于同一份资源操作时,会存在资源抢占,需要假如并发控制
- 线程会带来额外的开销,如cpu的调度时间,并发控制开销
- 每个线程在自己工作的内存交互,内存控制不当会造成数据不一致
2.线程的创建(重点)
Thread,Runable,Callable
main用户线程
gc守护线程
1.三种创建方式
Thread class | 继承Thread类(重点) |
---|---|
Runnable接口impl(重要) | 实现Runnable接口(重点) |
Callable接口 | Callable接口(了解) |
3.1Thread实现
- 创建一个类继承Thread
- 重写run方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
package com.kuang.demo01;
//创建线程方式一:继承Thread,重写run方法,调用start方法
public class TestThread1 extends Thread {
@Override
public void run() {
//run方法线程体
// 快速写循环20.for
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码----------"+i);
}
}
public static void main(String[] args) {
//main线程,主线程
//创建一个线程对象,调用start方法开启线程
TestThread1 testThread1 =new TestThread1();
testThread1.start();
/* testThread1.run();
当调用run方法时,先走run方法,而start方法时开启本线程,可以交替执行
*/
for (int i = 200; i > 0; i--) {
System.out.println("我在学习多线程+-------"+i);
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kG2jmaHi-1651654409853)(${images}/image-20210514113108405.png)]
总结:线程开辟不一定立即执行,由cpu调度执行
小栗子1.多线程下载图片
package com.kuang.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//ctrl+d直接复制
public class TestThread02 extends Thread{
//2.设置成员变量
private String url;
private String filename;
//3.初始化构造方法
public TestThread02(String url,String filename){
this.url=url;
this.filename=filename;
}
//4.重写run方法
@Override
public void run() {
WebDownload webDownload=new WebDownload();
webDownload.download(url,filename);
System.out.println("下载的文件名为:"+filename);
}
public static void main(String[] args) {
TestThread02 testThread1=new TestThread02("https://img0.baidu.com/it/u=2124865496,798253780&fm=11&fmt=auto&gp=0.jpg","1.jpg");
TestThread02 testThread2=new TestThread02("https://img1.baidu.com/it/u=1980119653,2367229126&fm=11&fmt=auto&gp=0.jpg","2.jpg");
TestThread02 testThread3=new TestThread02("https://img0.baidu.com/it/u=4087748813,965176217&fm=11&fmt=auto&gp=0.jpg","3.jpg");
testThread1.start();
testThread2.start();
testThread3.start();
}
}
//1.创建一个下载器
class WebDownload{
//下载方法
public void download(String url,String filename){
try {
FileUtils.copyURLToFile(new URL(url),new File(filename));
} catch (IOException e) {
e.printStackTrace();
System.out.println("io异常,download方法出现问题");
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FvNZ6Vfp-1651654409854)(${images}/image-20210514125808960.png)]
◆继承Thread类
◆子类继承Thread类具备多线程能力
◆启动线程:子类对象.start(0
◆不建议使用:避免OOP单继承局限性
3.2 runable接口实现
package com.kuang.demo01;
//创建线程方法2:思想runable接口,重写run方法,执行线程
public class TestTread03 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码----------"+i);
}
}
public static void main(String[] args) {
//创建runable接口实现类对象
TestTread03 testTread03 = new TestTread03();
new Thread(testTread03).start();
for (int i = 200; i > 0; i--) {
System.out.println("我在学习多线程+-------"+i);
}
}
}
实现Runnable接口
实现接口Runnable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g95nQQDA-1651654409854)(java多线程Img/image-20220316201744388.png)]
初始多并发
package com.kuang.demo01;
public class TestThread04 implements Runnable{
private int tickNum=10;
@Override
public void run() {
while (true){
if (tickNum<=0){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+tickNum--+"票");
}
}
public static void main(String[] args) {
TestThread04 ticket = new TestThread04();
new Thread(ticket,"小明").start();
new Thread(ticket,"小红").start();
new Thread(ticket,"黄牛").start();
}
}
3.3实现Callable接口(了解即可)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LkSnyE2k-1651654409854)(java多线程Img/image-20220316214506265.png)]
package com.kuang.demo02;
import com.kuang.demo01.TestThread02;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
/*
1、可以定义返回值
2、可以抛出异常
*/
public class TestCallable implements Callable<Boolean> {
//2.设置成员变量
private String url;
private String filename;
//3.初始化构造方法
public TestCallable(String url,String filename){
this.url=url;
this.filename=filename;
}
//4.重写run方法
@Override
public Boolean call() {
WebDownload webDownload=new WebDownload();
webDownload.download(url,filename);
System.out.println("下载的文件名为:"+filename);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable testThread1=new TestCallable("https://img0.baidu.com/it/u=2124865496,798253780&fm=11&fmt=auto&gp=0.jpg","1.jpg");
TestCallable testThread2=new TestCallable("https://img1.baidu.com/it/u=1980119653,2367229126&fm=11&fmt=auto&gp=0.jpg","2.jpg");
TestCallable testThread3=new TestCallable("https://img0.baidu.com/it/u=4087748813,965176217&fm=11&fmt=auto&gp=0.jpg","3.jpg");
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> submit1 = ser.submit(testThread1);
Future<Boolean> submit2= ser.submit(testThread2);
Future<Boolean> submit3 = ser.submit(testThread3);
//获取结果
Boolean res1 = submit1.get();
Boolean res2 = submit2.get();
Boolean res3 = submit3.get();
//关闭服务
ser.shutdown();
}
}
//1.创建一个下载器
class WebDownload{
//下载方法
public void download(String url,String filename){
try {
FileUtils.copyURLToFile(new URL(url),new File(filename));
} catch (IOException e) {
e.printStackTrace();
System.out.println("io异常,download方法出现问题");
}
}
}
ass WebDownload{
//下载方法
public void download(String url,String filename){
try {
FileUtils.copyURLToFile(new URL(url),new File(filename));
} catch (IOException e) {
e.printStackTrace();
System.out.println(“io异常,download方法出现问题”);
}
}
}
>未完待续