一.多线程简介
- 多任务:同时干很多件事,但是是分时进行,不同时间交替较快。
- 多线程:多条路线执行同一个任务。
多线程:主线程先调用start方法,然后子线程执行run()方法
程序,进程,线程:
在操作系统中运行的是进程,例如qq,播放器,游戏等,而一个进程可以有多个线程:例如,视频中同时听声音,看图像,看弹幕等
程序是静态的,进程是程序的执行(动态的),而一个进程至少含有一个线程(main线程等),线程是cpu调度和执行的单位
二.多线程的创建
1. 继承Thread类
- 注意:线程开启未必立即执行,由cpu调度执行,直接调用run方法,不会创建新的线程
线程创建
继承Thread类,重写run方法,调用start开启线程
package demo01;
//创建线程方式之一:继承Thread类,重写run方法,调用start开启线程
public class TestThead1 extends Thread{
@Override
public void run() { //run方法线程
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码+++"+i);
}
}
//main线程,主线程
public static void main(String[] args) {
//创建一个线程对象
TestThead1 testThead1 = new TestThead1();
//调用start()方法开启线程,两条线程交替执行
testThead1.start();
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程+++"+i);
}
}
}
//注意线程开启未必执行,由cpu调度执行
案例:多线程下载图片
在一个网页,下载它的三张图片
先编写下载器,然后到run(),最后再main函数中新建线程,然后启动线程
- 下载工具类及使用:
IDEA 引入jar包 以及 commons-io-2.6.jar包的使用
FileUtils.copyURLToFile(url, file) 的使用: Java 打开URL链接,并下载URL中的文件
代码:图片下载的顺序并不一致
package demo02;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//实现多线程同步下载网图
public class ThreadTest02 extends Thread{
private String url;//网络图片地址
private String name;//保存的文件名
@Override
public void run() {
WebDownLoader webDownLoader=new WebDownLoader();
webDownLoader.downloader(url,name);
System.out.println("下载了文件名为"+name);
}
//构造函数
public ThreadTest02(String url,String name) {
this.name=name;
this.url= url;
}
public static void main(String[] args) {
ThreadTest02 t1= new ThreadTest02("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&hs=2&pn=2&spn=0&di=68640&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=3788223672%2C2933772794&os=3469738239%2C2819470525&simid=0%2C0&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fimage.biaobaiju.com%2Fuploads%2F20191105%2F15%2F1572937434-vjDJNuBAxl.jpg%26refer%3Dhttp%3A%2F%2Fimage.biaobaiju.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1613979841%26t%3D6b74022d98f53152b4e7143934ed2714&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bktw5kwt37_z%26e3Bv54AzdH3Fi5g2geiwtztAzdH3Fl08nc_z%26e3Bip4s&gsm=3&islist=&querylist=","dog.jpeg");
ThreadTest02 t2=new ThreadTest02("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&hs=2&pn=5&spn=0&di=26840&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=2057173425%2C3288346039&os=3534193242%2C1744020036&simid=4255926711%2C726475710&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fimg.wohaoyun.com%2Fimg_600%2FM00%2F07%2FB8%2FwKjg2lvW-dGAERdjAAEeYGzmpUA906.jpg%26refer%3Dhttp%3A%2F%2Fimg.wohaoyun.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1613979935%26t%3Dbd8042b4b6488deae4c73854e0c4dd6e&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bo5iw5y7g_z%26e3Bv54AzdH3Ff3AzdH3F15g2o7ktzitAzdH3Fda8bAzdH3F88AzdH3F8988_z%26e3Bip4s&gsm=6&islist=&querylist=","dog2.jpeg");
ThreadTest02 t3=new ThreadTest02("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&hs=2&pn=4&spn=0&di=13750&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=2136279165%2C2845293579&os=1684394320%2C374773828&simid=3423840844%2C312231934&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fwww.cpnic.com%2FUploadFiles%2Fimg_0_3308088708_3867205912_26.jpg%26refer%3Dhttp%3A%2F%2Fwww.cpnic.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1613980066%26t%3D73944a43d2a1181ed0e4aeb6cd59da1e&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bvrgtv_z%26e3Bv54AzdH3FrtvAzdH3F%25Ec%25Ba%25bF%25Ec%25lE%25bB%25E0%25bB%25l0%25Ec%25ln%25b8%25E0%25A0%25bD%25Ec%25A9%25A0%25Ec%25bc%25Ab%25Ec%25bF%25bA%25Ec%25lB%25BE%25E0%25bl%25b0%25Ec%25bF%25bA%25E9%25BB%25B0%25Em%25Aa%25BCAzdH3F&gsm=5&islist=&querylist=","dog3.jpeg");
t1.start();
t2.start();
t3.start();
}
}
//下载器
class WebDownLoader{
public void downloader(String url,String name){
try{
FileUtils.copyURLToFile(new URL(url),new File(name));
}catch (IOException e){
e.printStackTrace();
System.out.println("IO异常,downloader方法出现问题");
}
}
}
2.实现Runnable接口(推荐)
区别:
public class TestThread03 implements Runnable{
@Override
public void run() { //run方法线程
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码+++"+i);
}
}
//main线程,主线程
public static void main(String[] args) {
// //创建Runnable接口实现类的对象
TestThread03 testThead3 = new TestThread03();
new Thread(testThead3).start();
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程+++"+i);
}
}
}
初识并发问题
看例子:
package demo03;
//买火车票
//多个线程操作同一个对象,会出现不同的线程抢到同一张票
public class TestThread04 implements Runnable{
@Override
public void run() {
while (true){
if (ticketNums<0){
break;
}
try { //快捷键 ctrl+alt+T
Thread.sleep(200); //模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"--->拿到了第"+ticketNums-- +"张票");
}
}
int ticketNums= 20;
public static void main(String[] args) {
TestThread04 t= new TestThread04();
new Thread(t,"小明").start();
new Thread(t,"小红").start();
new Thread(t,"小杠").start();
}
}
龟兔赛跑
package demo04;
public class race implements Runnable{
//只有一个胜利者
private static String winner;
public static void main(String[] args) {
race rubbit= new race(); //这是两个不同的线程
race tortise = new race();
new Thread(rubbit,"兔子").start();
new Thread(tortise,"乌龟").start();
}
@Override
public void run() {
for (int i = 0; i <=100; i++) {
//模拟兔子休息,每10步休息一下
if (Thread.currentThread().getName().equals("兔子")&&i%10==0)
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
//判断是否比赛结束
boolean flag = gameOver(i);
if (flag)
{
break;
}
}
}
//判断是否完成比赛
private boolean gameOver(int steps){
if (winner!=null){
return true;
}
{
if (steps>=100){
winner=Thread.currentThread().getName();
System.out.println("winner is "+ winner);
return true;
}
}
return false;
}
}
3.实现Callable接口(了解)
package demo02;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
//实现多线程同步下载网图
public class TestCallable implements Callable<Boolean> {
private String url;//网络图片地址
private String name;//保存的文件名
@Override
public Boolean call() {
WebDownLoader webDownLoader=new WebDownLoader();
webDownLoader.downloader(url,name);
System.out.println("下载了文件名为"+name);
return true;
}
//构造函数
public TestCallable(String url,String name) {
this.name=name;
this.url= url;
}
public static void main(String[] args) {
ThreadTest02 t1 = new ThreadTest02("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&hs=2&pn=2&spn=0&di=68640&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=3788223672%2C2933772794&os=3469738239%2C2819470525&simid=0%2C0&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fimage.biaobaiju.com%2Fuploads%2F20191105%2F15%2F1572937434-vjDJNuBAxl.jpg%26refer%3Dhttp%3A%2F%2Fimage.biaobaiju.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1613979841%26t%3D6b74022d98f53152b4e7143934ed2714&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bktw5kwt37_z%26e3Bv54AzdH3Fi5g2geiwtztAzdH3Fl08nc_z%26e3Bip4s&gsm=3&islist=&querylist=", "p.jpeg");
ThreadTest02 t2 = new ThreadTest02("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&hs=2&pn=5&spn=0&di=26840&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=2057173425%2C3288346039&os=3534193242%2C1744020036&simid=4255926711%2C726475710&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fimg.wohaoyun.com%2Fimg_600%2FM00%2F07%2FB8%2FwKjg2lvW-dGAERdjAAEeYGzmpUA906.jpg%26refer%3Dhttp%3A%2F%2Fimg.wohaoyun.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1613979935%26t%3Dbd8042b4b6488deae4c73854e0c4dd6e&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bo5iw5y7g_z%26e3Bv54AzdH3Ff3AzdH3F15g2o7ktzitAzdH3Fda8bAzdH3F88AzdH3F8988_z%26e3Bip4s&gsm=6&islist=&querylist=", "pp.jpeg");
ThreadTest02 t3 = new ThreadTest02("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&hs=2&pn=4&spn=0&di=13750&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=2136279165%2C2845293579&os=1684394320%2C374773828&simid=3423840844%2C312231934&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%B0%8F%E7%8B%97%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fwww.cpnic.com%2FUploadFiles%2Fimg_0_3308088708_3867205912_26.jpg%26refer%3Dhttp%3A%2F%2Fwww.cpnic.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1613980066%26t%3D73944a43d2a1181ed0e4aeb6cd59da1e&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bvrgtv_z%26e3Bv54AzdH3FrtvAzdH3F%25Ec%25Ba%25bF%25Ec%25lE%25bB%25E0%25bB%25l0%25Ec%25ln%25b8%25E0%25A0%25bD%25Ec%25A9%25A0%25Ec%25bc%25Ab%25Ec%25bF%25bA%25Ec%25lB%25BE%25E0%25bl%25b0%25Ec%25bF%25bA%25E9%25BB%25B0%25Em%25Aa%25BCAzdH3F&gsm=5&islist=&querylist=", "ppp.jpeg");
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);//线程池,放3个线程
//提交执行
Future<Boolean> r1 = (Future<Boolean>) ser.submit(t1);
Future<Boolean> r2 = (Future<Boolean>) ser.submit(t2);
Future<Boolean> r3 = (Future<Boolean>) ser.submit(t3);
/*获取结果
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get();
*/
//关闭服务
ser.shutdownNow();
}
}
//下载器
class WebDownLoader{
public void downloader(String url,String name){
try{
FileUtils.copyURLToFile(new URL(url),new File(name));
}catch (IOException e){
e.printStackTrace();
System.out.println("IO异常,downloader方法出现问题");
}
}
}