1、我的第一个多线程程序
方法一: extends Thread
package cn.hanquan.test;
public class StartThread extends Thread {
@Override
public void run() {// 线程入口点
for (int i = 0; i < 2000; i++) {
System.out.println("偷偷敲代码");
}
}
public static void main(String[] args) {
/*
* 启动线程
* 1、创建子类对象
* 2、调用子类对象的start方法
*/
StartThread st=new StartThread();
st.start();
for (int i = 0; i < 2000; i++) {
System.out.println("吃饭");
}
}
}
方法二:implements Runnable(推荐)
package cn.hanquan.test;
public class StartRun implements Runnable {
// 线程入口点
@Override
public void run() {
for (int i = 0; i < 1000; i++)
System.out.println("偷偷敲代码");
}
public static void main(String[] args) {
// 创建实现类对象
StartRun sr = new StartRun();
// 创建代理类对象
Thread t = new Thread(sr);
// 启动
t.start();
// 三合一:如果一个对象只是用一次,我们可以使用匿名
// new Thread(new StartRun()).start();
for (int i = 0; i < 1000; i++)
System.out.println("我在吃饭");
}
}
方法三:implements Callable(了解)
功能:多线程下载网页图片
package cn.hanquan.test;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.commons.io.FileUtils;
public class TDownloader implements Callable<Boolean> {
private String url;
private String name;
// 构造器
public TDownloader(String url, String name) {
this.url = url;
this.name = name;
}
// 线程入口点
@Override
public Boolean call() {
WebDownloader.download(url, name);
System.out.println("success");
return true;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
TDownloader cd1 = new TDownloader(
"https://img-blog.csdnimg.cn/20190724224219516.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzQyNDgzMzQx,size_16,color_FFFFFF,t_70",
"1.png");
TDownloader cd2 = new TDownloader(
"https://www.bjsxt.com/wp-content/themes/sxt/statics/images/bjsxt/images/share/project2.png", "2.png");
TDownloader cd3 = new TDownloader(
"https://img-blog.csdnimg.cn/20190722092922681.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzQyNDgzMzQx,size_16,color_FFFFFF,t_70",
"3.png");
// 创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
// 提交执行
Future<Boolean> result1 = ser.submit(cd1);
Future<Boolean> result2 = ser.submit(cd2);
Future<Boolean> result3 = ser.submit(cd3);
// 获取结果
boolean r1 = result1.get();
boolean r2 = result2.get();
boolean r3 = result3.get();
// 关闭服务
ser.shutdownNow();
}
}
//下载工具
class WebDownloader {
public static void download(String url, String name) {
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:可以看到,图片成功被下载
2、多线程下载图片
需要使用commons.io
package cn.hanquan.test;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
public class TDownloader extends Thread {
private String url;
private String name;
// 构造器
public TDownloader(String url, String name) {
this.url = url;
this.name = name;
}
// 线程入口点
@Override
public void run() {
WebDownloader.download(url, name);
System.out.println("success");
}
public static void main(String[] args) {
TDownloader t1 = new TDownloader(
"https://img-blog.csdnimg.cn/20190724224219516.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzQyNDgzMzQx,size_16,color_FFFFFF,t_70",
"1.png");
TDownloader t2 = new TDownloader(
"https://www.bjsxt.com/wp-content/themes/sxt/statics/images/bjsxt/images/share/project2.png", "2.png");
TDownloader t3 = new TDownloader(
"https://img-blog.csdnimg.cn/20190722092922681.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzQyNDgzMzQx,size_16,color_FFFFFF,t_70",
"3.png");
t1.start();
t2.start();
t3.start();
}
}
//下载工具
class WebDownloader {
public static void download(String url, String name) {
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.使用多线程模拟抢票
出现重复数字的原因是:线程不安全
package cn.hanquan.test;
public class StartRun implements Runnable {
public static int ticket = 100;
// 线程入口点
@Override
public void run() {
while (ticket > 0) {
//ticket--;
System.out.println(Thread.currentThread().getName() + "->" + ticket--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 三合一:如果一个对象只是用一次,我们可以使用匿名
new Thread(new StartRun(), "小红").start();
new Thread(new StartRun(), "魔鬼").start();
new Thread(new StartRun(), "布谷鸟").start();
}
}
部分结果