每日笔记之多线程三种创建方式
1、继承Thread类,重写run()方法,调用start开启线程
总结:线程开启start()不一定立即执行,由CPU调度执行,调用run()方法立即执行
原因:调用run()方法,主线程先调用run()方法,再执行后面的方法,而调用start()方法,相当于开启了两个线程,交替执行。
例:多个线程同时下载图片
package com.zuoyan.lesson01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* 多个线程同时下载图片
*/
public class ThreadDownFile extends Thread{
//图片地址
private String url;
//文件名称
private String name;
public ThreadDownFile(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 static void main(String[] args) {
ThreadDownFile thread1 = new ThreadDownFile("http://www.kennerchina.cn/upload/show/68dfcf42-6c7a-4060-bc9e-deb4ad321c9e-banner.jpg", "1.jpg");
ThreadDownFile thread2 = new ThreadDownFile("http://www.kennerchina.cn/upload/showPageConfig/50830201-bee8-4348-812e-c59dd31905d6-Sky2.jpg", "2.jpg");
ThreadDownFile thread3 = new ThreadDownFile("http://www.kennerchina.cn/upload/showStyle/45082cd1-75d8-4a56-a1ec-9c16399f7964-kenner-70.png", "3.jpg");
thread1.start();
thread2.start();
thread3.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接口,重写run()方法
执行线程时丢入runnable接口实现类,调用start()方法
package com.zuoyan.lesson01;
/**
* 创建线程方式2:实现runnable接口,重写run()方法,执行线程时丢入runnable接口实现类,调用start()方法
*/
public class RunnableThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("测试run()方法:" + i);
}
}
public static void main(String[] args) {
RunnableThread runnableThread = new RunnableThread();
//创建线程对象,通过线程对象来开启线程,代理,调用start()方法
new Thread(runnableThread).start();
for (int i = 0; i < 200; i++) {
System.out.println("主方法:" + i);
}
}
}
3、实现Callable接口,重写call方法,有返回值
package com.zuoyan.lesson01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
/**
* 创建多线程方式三:实现Callable接口,重写call()方法
*/
public class CallableThread implements Callable<Boolean> {
private String url;
private String name;
public CallableThread(String url, String name) {
this.url = url;
this.name = name;
}
@Override
public Boolean call() throws Exception {
WebDownLoader2 webDownLoader = new WebDownLoader2();
webDownLoader.downLoader(url, name);
System.out.println("下载了文件:" + name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallableThread t1 = new CallableThread("https://pics7.baidu.com/feed/adaf2edda3cc7cd97ab1d177f1e8cb38ba0e91f6.jpeg?token=0790121cb37f3897c85b66b702fad038&s=A832C614642000BA870E7E820300709C", "1.jpg");
CallableThread t2 = new CallableThread("https://pics4.baidu.com/feed/f2deb48f8c5494ee8d49b8a086130af998257e0a.png?token=4cb1c7eb18cacf1b48120659b6256554&s=B123DC14C770418E1F5AF1490300F0B9", "2.jpg");
CallableThread t3 = new CallableThread("https://pics3.baidu.com/feed/d1160924ab18972bb05edb52422b918e9f510a34.png?token=ad07ba0717cb7900ec8eafd0a0aeda8b&s=40085F320DDECCCE105061D9030050B2", "3.jpg");
//创建服务执行(创建3个线程)
ExecutorService service = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1 = service.submit(t1);
Future<Boolean> r2 = service.submit(t2);
Future<Boolean> r3 = service.submit(t3);
//获取结果
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get();
//打印返回值结果
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
///关闭服务
service.shutdownNow();
}
}
class WebDownLoader2{
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方法出现问题");
}
}
}
3、小结
-
继承Thread类
: 子类继承Thread类具备多线程能力
: 启动方式:子类对象.start()
: 不建议使用:避免OOP单继承局限性 -
实现runnable接口
: 实现接口runnable具备多线程能力
: 启动线程:传入目标对象+Thread对象.start()
: 推荐使用:避免单继承的局限性,灵活方便,方便一个对象可供多个线程使用 -
实现Callable接口
: 可以定义返回值
: 可以抛出异常