一.java多线程基本概念

调用run():在主线程调用子线程的run()方法会中断主线程等到子线程执行完毕之后再执行主线程。

调用start():在主线程中执行子线程的start()后会与主线程同步执行。

二.线程创建的三种方法

Thread、Runnable、Callable

1.Thread入门

步骤:

  • 继承Thread类
  • 重写run方法
  • 调用start开启线程
 //创建线程方式一步骤:继承Thread类,重写run方法,调用start开启线程
public class test01 extends Thread{ @Override
public void run() {
for (int i = 0; i < 10;i++){
System.out.println("run方法执行..." + i);
}
} public static void main(String[] args) { //创建线程对象
test01 t1 = new test01(); //开启线程
t1.start(); for (int i = 0; i < 1000; i++){
System.out.println("main方法执行..." + i);
}
}
}

执行结果:交替执行

练习:使用Thread实现多线程同步下载图片

(1).导入依赖的jar包:

    <dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

(2).编写test02.java:

 /**
* 使用多线程下载图片
* @author USTC_WZH
* @create 2019-12-05 11:26
*/
public class test02 extends Thread { //图片url地址
private String url;
//保存的文件名
private String name; public test02(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) {
test02 t1 = new test02("http://lswhw.ustc.edu.cn/upload/20150427/20150427102635.jpg", "images/图片1.jpg");
test02 t2 = new test02("http://lswhw.ustc.edu.cn/upload/20150427/20150427103657.jpg", "images/图片2.jpg");
test02 t3 = new test02("http://lswhw.ustc.edu.cn/upload/20150427/20150427103010.jpg", "images/图片3.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("downloader方法出现异常");
}
}
}

2.实现Runable接口(重点使用)

三个步骤:

  • 实现Runnable接口,重写run方法
  • 执行线程需要丢入Runnable接口的实现类
  • 调用start方法

 /**
* 创建线程方法二步骤:
* 1.实现Runnable接口,重写run方法。
* 2.执行线程需要丢入runnable接口的实现类。
* 3.调用start方法。
* @author USTC_WZH
* @create 2019-12-05 14:14
*/
public class test03 implements Runnable{ @Override
public void run() {
for (int i = 0; i < 10;i++){
System.out.println("run方法执行..." + i);
}
} public static void main(String[] args) { //创建runnable接口的实现类对象
test01 t1 = new test01(); //创建线程对象,通过线程对象来开启我们的线程,代理模式
new Thread(t1).start(); for (int i = 0; i < 1000; i++){
System.out.println("main方法执行..." + i);
}
}
}

补充:模拟并发问题

 /**
* 模拟买火车票
*
* @author USTC_WZH
* @create 2019-12-05 14:32
*/
public class testerror implements Runnable { //火车票个数
private int ticketNums = 10; @Override
public void run() { while (true) { if (ticketNums <= 0) {
break;
} //模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(Thread.currentThread().getName() + "-->拿了第" + ticketNums-- + "票");
}
} public static void main(String[] args) { testerror t = new testerror(); new Thread(t, "小明").start();
new Thread(t, "小红").start();
new Thread(t, "花花").start();
}
}

当同一个对象被多个线程访问时出现的并发错误的问题!

3.实现Callable接口(了解)

步骤:7步

  • 实现Callable接口,需要返回值类型
  • 重写call方法,需要抛出异常
  • 创建目标对象
  • 创建执行服务
  • 提交执行
  • 获取结果
  • 关闭服务
 package ustc.wzh.callable;

 import org.apache.commons.io.FileUtils;

 import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*; /**
* @author USTC_WZH
* @create 2019-12-05 14:44
* <p>
* 创建线程方式三步骤:
* 1.实现Callable接口,需要返回值类型
* 2.重写call方法,需要抛出异常
* 3.创建目标对象
* 4.创建执行服务
* 5.提交执行
* 6.获取结果
* 7.关闭服务
*/
//1.实现Callable接口
public class testCallable implements Callable<Boolean> { //图片url地址
private String url;
//保存的文件名
private String name; public testCallable(String url, String name) {
this.url = url;
this.name = name;
} //2.重写call方法
@Override
public Boolean call() throws Exception {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url, name);
System.out.println("下载文件名:" + name);
return true;
} public static void main(String[] args) throws ExecutionException, InterruptedException { //创建目标对象
testCallable t1 = new testCallable("http://lswhw.ustc.edu.cn/upload/20150427/20150427102635.jpg", "images/图片1.jpg");
testCallable t2 = new testCallable("http://lswhw.ustc.edu.cn/upload/20150427/20150427103657.jpg", "images/图片2.jpg");
testCallable t3 = new testCallable("http://lswhw.ustc.edu.cn/upload/20150427/20150427103010.jpg", "images/图片3.jpg"); //4.创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3); //5.提交执行
Future<Boolean> r1 = ser.submit(t1);
Future<Boolean> r2 = ser.submit(t2);
Future<Boolean> r3 = ser.submit(t3); //6.获取结果
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get(); System.out.println("rs1=" + rs1 + ",rs2=" + rs2 + ",rs3=" + rs3); //7.关闭服务
ser.shutdownNow();
} } 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("downloader方法出现异常");
}
}
}

最新文章

  1. 【白话设计模式四】单例模式(Singleton)
  2. log4j分离日志输出 自定义过滤 自定义日志文件
  3. ElasticSearch的各种服务的URL
  4. C++变量对比java变量所占内存
  5. Chrome Apps將是Google送給微軟的特洛伊木馬?
  6. 小波说雨燕 第三季 构建 swift UI 之 度假清单 学习笔记
  7. 【leetcode】Palindrome Partitioning II
  8. Nodejs之socket广播
  9. OA学习笔记-010-Struts部分源码分析、Intercepter、ModelDriver、OGNL、EL
  10. java中的浮点(float)运算
  11. keil c51的内部RAM(idata)动态内存管理程序
  12. cmd第一次推送github
  13. Quartz (二) 和Spring整合
  14. Django 个性化管理员站点
  15. PA模块常用表
  16. Bigger-Mai 养成计划,Docker之安装,部署
  17. 浅谈SQL注入
  18. leetcode 翻转二叉树
  19. 胖哈勃杯Pwn400、Pwn500详解
  20. 最新Android &amp; iOS设计尺寸规范

热门文章

  1. HTML的attribute和DOM的property剖析(转)
  2. 如何判断两个IP地址是不是处于同一网段?
  3. C#写入Excel文件方式
  4. mvc_第一章后入门_第一遍_控制器和视图
  5. mybatis日志,打印sql语句,输出sql
  6. Django---FORM组件.FORM组件的字段,FORM组件校验流程,FORM组件的全局和局部钩子,FORM和Model的组合
  7. ajxa和axios的区别
  8. 微信小程序调用云函数出错 Error: errCode: -404011 cloud function execution error | errMsg: cloud.callFunction:fail cloud function service error code -501005, error message Environment not found;
  9. SparkStreaming之checkpoint检查点
  10. Docker搭建Zentao(禅道)