JVM中的基本线程

main线程

用户编写的代码都在该线程中。

GC线程

垃圾回收线程。

Java中多线程的实现方式

继承Thread类

  • 自定义线程类并继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程

注意:线程启动需要时间。

简单示例

下面是一个简单的例子:

  1. public class TestThread01 extends Thread{
  2. /**
  3. * run方法线程体
  4. */
  5. @Override
  6. public void run() {
  7. for (int i = 0; i < 20; i++) {
  8. System.out.println("information--"+i);
  9. }
  10. }
  11. // main线程
  12. public static void main(String[] args) {
  13. // 创建线程对象
  14. TestThread01 thread01 = new TestThread01();
  15. // 调用start方法
  16. thread01.start();
  17. for (int i = 0; i < 20; i++) {
  18. System.out.println("我在学习多线程"+i);
  19. }
  20. }
  21. }

输出:

  1. 我在学习多线程0
  2. 我在学习多线程1
  3. 我在学习多线程2
  4. 我在学习多线程3
  5. 我在学习多线程4
  6. 我在学习多线程5
  7. 我在学习多线程6
  8. 我在学习多线程7
  9. 我在学习多线程8
  10. 我在学习多线程9
  11. 我在学习多线程10
  12. information--0
  13. 我在学习多线程11
  14. 我在学习多线程12
  15. 我在学习多线程13
  16. information--1
  17. 我在学习多线程14
  18. information--2
  19. information--3
  20. information--4
  21. information--5
  22. information--6
  23. information--7
  24. information--8
  25. information--9
  26. information--10
  27. 我在学习多线程15
  28. information--11
  29. 我在学习多线程16
  30. information--12
  31. 我在学习多线程17
  32. information--13
  33. 我在学习多线程18
  34. 我在学习多线程19
  35. information--14
  36. information--15
  37. information--16
  38. information--17
  39. information--18
  40. information--19

可以看到主线程(main)和自定义线程间是交替输出语句的。

多线程图片下载器

下面是一个简单的多线程实现的网络图片下载器:

  1. /**
  2. * 多线程实现同步图片下载
  3. */
  4. public class TestThread02 extends Thread{
  5. private String url; // 图片地址
  6. private String name; // 保存地址
  7. public TestThread02(String url, String name) {
  8. this.url = url;
  9. this.name = name;
  10. }
  11. @Override
  12. public void run() {
  13. // 实例化网络下载器进行下载
  14. WebDownloader downloader = new WebDownloader();
  15. downloader.downloader(url, name);
  16. System.out.println("下载执行完毕:" + name);
  17. }
  18. public static void main(String[] args) {
  19. String url1 = "https://i0.hdslb.com/bfs/archive/e10a58ac1f802126bc56d709350365e5a13d0f57.jpg"; // 图片地址
  20. String url2 = "https://i2.hdslb.com/bfs/archive/8b3c6c5e975dfe5cd0cfe98af82710242412f2d8.jpg";
  21. String url3 = "https://i0.hdslb.com/bfs/archive/e8c0ac051bbd998967fbd8df397c174afbaf5e4b.jpg";
  22. // 实例化线程类
  23. TestThread02 thread02 = new TestThread02(url1, "img/1.jpg");
  24. TestThread02 thread03 = new TestThread02(url2, "img/2.jpg");
  25. TestThread02 thread04 = new TestThread02(url3, "img/3.jpg");
  26. // 启动下载
  27. thread02.start();
  28. thread03.start();
  29. thread04.start();
  30. }
  31. }
  32. class WebDownloader {
  33. public void downloader(String url, String name) {
  34. try {
  35. FileUtils.copyURLToFile(new URL(url), new File(name));
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. System.out.println("IO异常,downloader方法出现问题");
  39. }
  40. }
  41. }

其中FileUtils的依赖为:

  1. <dependency>
  2. <groupId>commons-io</groupId>
  3. <artifactId>commons-io</artifactId>
  4. <version>2.2</version>
  5. </dependency>

输出结果:

  1. 下载执行完毕:img/3.jpg
  2. 下载执行完毕:img/2.jpg
  3. 下载执行完毕:img/1.jpg
  4. Process finished with exit code 0

image.png

实现Runnable接口

  • 自定义类实现Runnable接口的run方法
  • 实例化Thread类并将自定义类(实现了Runnable接口)作为构造器参数传入
  • 调用Thread实例的start方法启动线程

注意:该种实现方式使用了静态代理,Thread类也实现了该接口

改造图片下载器

  1. /**
  2. * 改为使用Runnable接口实现图片下载
  3. */
  4. class TestThread02Runnable implements Runnable{
  5. private String url; // 图片地址
  6. private String name; // 保存地址
  7. public TestThread02Runnable(String url, String name) {
  8. this.url = url;
  9. this.name = name;
  10. }
  11. @Override
  12. public void run() {
  13. WebDownloader downloader = new WebDownloader();
  14. downloader.downloader(url, name);
  15. System.out.println("下载执行完毕:" + name);
  16. }
  17. public static void main(String[] args) {
  18. String url1 = "https://i0.hdslb.com/bfs/archive/e10a58ac1f802126bc56d709350365e5a13d0f57.jpg"; // 图片地址
  19. String url2 = "https://i2.hdslb.com/bfs/archive/8b3c6c5e975dfe5cd0cfe98af82710242412f2d8.jpg";
  20. String url3 = "https://i0.hdslb.com/bfs/archive/e8c0ac051bbd998967fbd8df397c174afbaf5e4b.jpg";
  21. // 实现Runnable接口
  22. TestThread02Runnable thread02 = new TestThread02Runnable(url1, "img/1.jpg");
  23. TestThread02Runnable thread03 = new TestThread02Runnable(url2, "img/2.jpg");
  24. TestThread02Runnable thread04 = new TestThread02Runnable(url3, "img/3.jpg");
  25. // 实例化线程并启动线程
  26. new Thread(thread02).start();
  27. new Thread(thread03).start();
  28. new Thread(thread04).start();
  29. }
  30. }
  31. class WebDownloader {
  32. public void downloader(String url, String name) {
  33. try {
  34. FileUtils.copyURLToFile(new URL(url), new File(name));
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. System.out.println("IO异常,downloader方法出现问题");
  38. }
  39. }
  40. }

输出没有变化,这里就不再赘述。