方法1:继承Thread类
简介
- 创建多线程的方法1:继承Thread类,重写run()方法。
- 注意:慎用,因为java中只能单继承。
- Thread类实现了Runnable接口,Runnable接口应由任何类实现,其实例由线程执行。该类必须定义一个无参的run方法。
- Java虚拟机允许应用程序同时执行多个线程。线程分为守护线程和用户线程,JVM必须等到所有用户线程执行完后才停止,而不需要等待守护线程。
- 创建线程的具体操作:继承Thread类—>重写run()方法—>创建一个实例,并调用start()方法启动线程。
- start():并不是马上执行线程,而是交给CPU去调用,什么时候调用到,什么时候执行。
- 需要注意创建线程的时机。
- 线程执行run()方法。
测试
code
/**
* 创建 线程
* 方法1:继承Thread类+重写run()
* 缺陷:java中一个类只能继承一个类
*
*/
public class StartThread extends Thread {
/**
* 重写run()方法
*/
public void run(){
for(int i=0; i<20; i++){
System.out.println("幽暗的丛林中分出了两条路"+i);
}
}
public static void main(String[] args){
//创建子类对象
StartThread st = new StartThread();
//启动, 开启一个线程,交给CPU调用,程序不会等这个线程执行完
st.start();
for(int i=0; i<20; i++){
System.out.println("是两条线程呢"+i);
}
}
}
利用多线程实现网络下载图片
code1:下载方法
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
/**
* 下载网上的图片
* @author dxt
*
*/
public class WebDownLoader {
public void download(String url, String name){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (MalformedURLException e) {
e.printStackTrace();
System.out.println("不合法的url");
} catch (IOException e) {
e.printStackTrace();
System.out.println("图片下载失败");
}
}
}
code2:使用多线程调用下载方法
/**
* 利用多线程下载网上的图片
* @author dxt
*
*/
public class ThreadDownloader extends Thread{
private String url; //远程路径
private String name; //存储地址
public ThreadDownloader(){}
public ThreadDownloader(String url, String name){
this.url = url;
this.name = name;
}
/**
* 重写run()方法
* 调用WebDownloader中的方法
*/
public void run(){
WebDownLoader wd = new WebDownLoader();
wd.download(url, name);
}
public static void main(String[] args){
ThreadDownloader td1 = new ThreadDownloader("http://a0.att.hudong.com/78/52/01200000123847134434529793168.jpg", "tiger.jpg");
ThreadDownloader td2 = new ThreadDownloader("http://a4.att.hudong.com/21/09/01200000026352136359091694357.jpg", "bird.jpg");
ThreadDownloader td3 = new ThreadDownloader("http://img.52z.com/upload/news/20191105/1572917170776440suo.jpg", "girl.jpg");
//启动三个线程,这三个线程在下载过程中没有先后顺序
td1.start();
td2.start();
td3.start();
}
}
方法2:实现Runnable接口
简介
创建多线程的方法2:实现Runnable接口,重写run()方法。
创建线程的具体操作:实现Runnable接口—>重写run()方法—>创建一个实例,借用Thread对象来启动线程。
测试
code
/**
* 创建线程
* 方法2 实现Runnable接口 + 重写run()方法 + 使用Thread调用
* 一般创建线程时使用此方法,避免单继承的局限性
* @author dxt
*
*/
public class StartRun implements Runnable{
/**
* 实现run()方法
*/
public void run(){
for(int i=0; i<20; i++){
System.out.println("幽暗的丛林中分出了两条路"+i);
}
}
public static void main(String[] args){
//创建实现类对象
StartRun sr = new StartRun();
//创建代理类对象
Thread t = new Thread(sr);
//启动
t.start();
for(int i=0; i<20; i++){
System.out.println("是两条线程呢"+i);
}
}
}
共享资源测试
code
/**
* 测试第二种方法创建线程时共享资源的性质,模拟12306抢票程序
* 共享资源会产生并发问题
* @author dxt
*
*/
public class Web12306 implements Runnable{
private int ticketNums = 99; //票数
/**
* 实现run()方法
* run()方法不要抛出异常,而是使用try--catch处理异常
*/
public void run(){
while(true){
if(ticketNums < 0){
break;
}
System.out.println(Thread.currentThread().getName() + ticketNums--);
}
}
public static void main(String[] args){
//一份资源
Web12306 web = new Web12306();
//多个线程使用,三个线程
new Thread(web, "1dxt").start();
new Thread(web, "2dxt").start();
new Thread(web, "3dxt").start();
}
}
方法3:实现Callable接口
创建多线程的方法3:实现Callable接口,重写call()方法。
测试
code
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;
/**
* 测试Callable方法创建线程
* @author dxt
*
*/
public class CDownloader implements Callable<Boolean>{
private String url; //远程路径
private String name; //存储地址
public CDownloader(){}
public CDownloader(String url, String name){
this.url = url;
this.name = name;
}
/**
* 重写call()方法
*/
public Boolean call() throws Exception {
WebDownLoader wd = new WebDownLoader();
wd.download(url, name);
return null;
}
public static void main(String[] args) throws InterruptedException, ExecutionException{
CDownloader cd1 = new CDownloader("http://a0.att.hudong.com/78/52/01200000123847134434529793168.jpg", "tiger.jpg");
CDownloader cd2 = new CDownloader("http://a4.att.hudong.com/21/09/01200000026352136359091694357.jpg", "bird.jpg");
CDownloader cd3 = new CDownloader("http://img.52z.com/upload/news/20191105/1572917170776440suo.jpg", "girl.jpg");
//创建执行服务
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 = result1.get();
boolean r3 = result1.get();
//关闭服务
ser.shutdownNow();
}
}