目录
1.初识多线程
2.线程创建
(1)Thread
(2)Runnable
3.并发初步
(1)引入:
(2)并发——龟兔赛跑
3.了解Callable接口(扩充)
1.初识多线程
2.线程创建
(1)Thread
代码测试:
结果:(可以看出start()之后,这个线程和主线程是一起执行的)
注意,线程开启不一定立即执行,是由你这台电脑的cpu调度执行的
这里手写下载图片的案例:
//联系Thread,实现多线程同步下载图片
public class TestThread extends Thread {
public static void main(String[] args) {
TestThread t1 = new TestThread("https://i1.hdslb.com/bfs/face/84eb66503a34422d79734910da0ded75ed8da144.jpg@160w_160h_1c_1s.webp"
, "number1.jpg");
TestThread t2 = new TestThread("https://i2.hdslb.com/bfs/face/83bb511365da513c55aa3d1958524f3b7db40684.jpg@120w_120h_1c_1s.webp",
"number2.jpg");
TestThread t3 = new TestThread("https://i0.hdslb.com/bfs/sycp/creative_img/202105/776456a3714a2ec0d530f2cc65e1832c.jpg@.webp",
"number3.jpg");
t1.start();
t2.start();
t3.start();
}
private String url;
private String name;
public TestThread() {
}
public TestThread(String url, String name) {
this.url = url;
this.name = name;
}
//下载图片的线程执行体
@Override
public void run() {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downloader(url,name);
System.out.println("下载的文件名:"+name);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String toString() {
return "Test{url = " + url + ", name = " + name + "}";
}
}
//下载器
class WebDownLoader {
//下载方法
public void downloader(String url, String name) {
//注意要导入io里面的fileutils
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,downloader方法出现问题");
}
}
}
结果如下:(说明不是按代码顺序执行,而是同时执行)
(2)Runnable
代码实例:
package com.example;
//创建线程方式2:实现runnable接口,重写run方法
//执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread2 implements Runnable {
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 200; i++) {
System.out.println("嘿!" + i);
}
}
public static void main(String[] args) {
//创建runnable接口的实现类对象
TestThread2 testThread2 = new TestThread2();
//创建线程对象,通过线程对象来开启我们的线程...
//Thread thread = new Thread(testThread2);
//thread.start();
new Thread(testThread2).start();
for (int i = 0; i < 800; i++) {
System.out.println("啦啦啦啦" + i);
}
}
}
结果:
3.并发初步
(1)引入:
实例:
如果太快,观察不出来可以用个延时,如下:
结果:
所以多个线程操作同一个资源时,线程不安全,数据也紊乱
(2)并发——龟兔赛跑
public class Race implements Runnable {
//胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
//判断比赛是否结束
boolean flag = gamerOver(i);
if (flag) {
break;
}
//打印线程名字
System.out.println(Thread.currentThread().getName() +
"——>跑了" + i + "步");
}
}
//判断是否完成比赛
private boolean gamerOver(int steps) {
if (winner != null) {
return true;
}
if (steps >= 100) {
winner = Thread.currentThread().getName();
System.out.println("winner is " + winner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race, "兔子").start();
new Thread(race, "乌龟").start();
}
}
结果:
可以模拟兔子休息:
//模拟兔子休息:
if(Thread.currentThread().getName().equals("兔子")){
try {
Thread.sleep(210);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
3.了解Callable接口(扩充)
用上面下载图片的例子改一下:首先是run变成call,并且有返回值
然后主体运行逻辑代码也不一样
所以:callable可以定义返回值,也能抛出异常,
学习的课程:【狂神说Java】多线程详解_哔哩哔哩_bilibili
暑期编程PK赛 得CSDN机械键盘等精美礼品!


