https://space.bilibili.com/95256449/channel/detail?cid=146244
Java中的多线程001
1、继承Thread类,重写run方法,创建线程对象,调用start()方法
package com.stark.study;
//创建线程方式一:继承Thread类,重写run()方法,调用start()开启线程
public class TestThread extends Thread {
//重写run方法
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("副线程" + i);
}
}
//main线程,主线程
public static void main(String[] args) {
//创建线程对象
TestThread testThread = new TestThread();
//调用start()方法启动副线程
testThread.start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程" + i);
}
}
}
2、使用Apache的commons io 和多线程下载图片
package com.stark.study;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//练习Thread,实现多线程同步下载图片
public class TestThread2 extends Thread {
private String url;//网络地址
private String name;//保存的文件名
public TestThread2(String url,String name) {
this.url = url;
this.name = name;
}
//重写run方法
@Override
public void run() {
// super.run();
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println(name + "文件已下载");
}
public static void main(String[] args) {
TestThread2 t1 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","picture001.jpg");
TestThread2 t2 = new TestThread2("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/baiduyun@2x-e0be79e69e.png","picture002.jpg");
TestThread2 t3 = new TestThread2("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/tupian@2x-482fc011fc.png","picture003.jpg");
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异常,WebDownloader.downloader()方法异常。");
}
}
}
3、 创建线程的另一种方法是声明一个实现Runnable接口的类。 该类然后实现run方法。 然后可以分配类的实例,再创建Thread时作为参数传递,然后启动。
package com.stark.study;
//创建线程方式2:实现Runnable接口,重写run方法, 然后可以分配类的实例,再创建Thread时作为参数传递,然后启动。
public class TestThread3 implements Runnable {
//重写run方法
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("副线程" + i);
}
}
//main线程,主线程
public static void main(String[] args) {
//创建Runnable接口的实现类对象
TestThread3 testThread3 = new TestThread3();
//创建Thread类的对象,将Runnable的实现类对象作为参数传入,然后启动线程
// Thread thread = new Thread(testThread3);
// thread.start();
new Thread(testThread3).start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程" + i);
}
}
}
4、 多线程操作同一个对象,线程不安全,存在并发问题
package com.stark.study;
//多个线程同时操作同一个对象
//买火车票的例子
//多个线程操作同一个对象时,线程不安全,数据紊乱,存在并发问题
public class TestThread4 implements Runnable {
//票数
private int ticketNums = 30;
@Override
public void run() {
while (true)
{
if (0 >= ticketNums)
{
break;
}
System.out.println(Thread.currentThread().getName() + "--拿到了第" + ticketNums-- + "票");
//延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestThread4 ticket = new TestThread4();
//多线程操作同一个对象
new Thread(ticket,"学生").start();
new Thread(ticket,"老师").start();
new Thread(ticket,"黄牛").start();
}
}
5、 龟兔赛跑
package com.stark.study;
public class Race implements Runnable {
private static String winner;//胜利者
@Override
public void run() {
for (int i = 0; i <= 1000; i++) {
//判断比赛是否结束
boolean flag = gameOver(i);
if (flag){
break;
}
//模拟兔子休息
if (Thread.currentThread().getName().equals("兔子") && (i%10 == 0)){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "--跑了" + i + "步");
}
}
//判断是否完成比赛
private boolean gameOver(int steps) {
//判断是否有胜利者
if (null != winner) {
return true;
}
if (steps >= 1000){
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();
}
}