1.线程的概念:线程(thread)是指一个任务从头至尾的执行流,线程提供一个运行任务的机制,对于java而言,一个程序中可以并发的执行多个线程,这些线程可以在多处理器系统上同时运行。当程序作为一个应用程序运行时,java解释器为main()方法启动一个线程。

2.并行与并发:

(1)并发:在单处理器系统中,多个线程共享CPU时间,而操作系统负责调度及分配资源给它们。

(2)并行:在多处理器系统中,多个处理器可以同时运行多个线程,这些线程在同一时间可以同时运行,而不同于并发,只能多个线程共享CPU时间,同一时间只能运行一个线程。

3.线程的创建:

(1)基础概念:java中每个任务就是一个可运行对象,为了创建任务,必须首先定义任务类,任务类必须实现Runnable接口。而线程本质上讲就是便于任务执行的对象。一个线程的执行过程就是一个任务类中run()方法的执行到结束。

(2)通过Runnable接口创建线程:

  a.定义一个任务类实现Runnable接口,实现Runnable接口中的run()方法(run()方法告知系统线程该如何运行),run()方法中定义具体的任务代码或处理逻辑。

  b.定义了任务类后,为任务类创建一个任务对象。

  c.任务必须在线程中执行,创建一个Tread类的对象,将前面创建的实现了Runnable接口的任务类对象作为参数传递给Tread类的构造方法。

  d.调用Tread类对象的start()方法,启动一个线程。它会导致任务的run()方法被执行,当run()方法执行完毕,则线程就终止。

  实例代码:

 1 package com.muzeet.mutithread;
 2
 3 //每个任务都是Runable接口的一个实例,任务是可运行对象,线程是便于任务执行的对象。必须创建任务类,重写run方法定义任务
 4 public class ThreadDemo1 implements Runnable {
 5     private int countDown = 10;
 6     @Override
 7     //重写run方法,定义任务
 8     public void run() {
 9         while(countDown-- >0)
10         {
11             System.out.println("$" + Thread.currentThread().getName()
12                     + "(" + countDown + ")");
13         }
14     }
15     //调用start方法会启动一个线程,导致任务中的run方法被调用,run方法执行完毕则线程终止
16
17     public static void main(String[] args) {
18         Runnable demo1 = new ThreadDemo1();
19
20         Thread thread1 = new Thread(demo1);
21         Thread thread2 = new Thread(demo1);
22         thread1.start();
23         thread2.start();
24
25         System.out.println("火箭发射倒计时:");
26
27
28     }
29
30 }

  程序运行结果:

火箭发射倒计时:
$Thread-0(9)
$Thread-0(8)
$Thread-0(7)
$Thread-0(6)
$Thread-0(5)
$Thread-0(4)
$Thread-0(3)
$Thread-0(2)
$Thread-0(1)
$Thread-0(0)

  同时运行两个任务对象:

  

public static void main(String[] args) {Runnable demo1 = new ThreadDemo1();Runnable demo2 = new ThreadDemo1();Thread thread1 = new Thread(demo1);Thread thread2 = new Thread(demo2);thread1.start();thread2.start();System.out.println("火箭发射倒计时:");}

  运行结果:

火箭发射倒计时:
$Thread-0(9)
$Thread-0(8)
$Thread-0(7)
$Thread-0(6)
$Thread-1(9)
$Thread-0(5)
$Thread-1(8)
$Thread-0(4)
$Thread-1(7)
$Thread-0(3)
$Thread-1(6)
$Thread-1(5)
$Thread-0(2)
$Thread-1(4)
$Thread-1(3)
$Thread-1(2)
$Thread-1(1)
$Thread-1(0)
$Thread-0(1)
$Thread-0(0)

  

(3)继承Thread类来创建线程: 

  a.首先创建一个任务类extends Thread类,因为Thread类实现了Runnable接口,所以自定义的任务类也实现了Runnable接口,重新run()方法,其中定义具体的任务代码或处理逻辑。

  b.创建一个任务类对象,可以用Thread或者Runnable作为自定义的变量类型。

  c.调用自定义对象的start()方法,启动一个线程。

  示例代码:

 1 package com.muzeet.mutithread;
 2
 3 //每个任务都是Runable接口的一个实例,任务是可运行对象,线程即可运行对象。必须创建任务类,重写run方法定义任务
 4 public class ExtendFromThread extends Thread {
 5     private int countDown = 10;
 6     @Override
 7     //重写run方法,定义任务
 8     public void run() {
 9         while(countDown-- >0)
10         {
11             System.out.println("$" + this.getName()
12                     + "(" + countDown + ")");
13         }
14     }
15     //调用start方法会启动一个线程,导致任务中的run方法被调用,run方法执行完毕则线程终止
16
17     public static void main(String[] args) {
18
19         ExtendFromThread thread1 = new ExtendFromThread();
20         ExtendFromThread thread2 = new ExtendFromThread();
21         thread1.start();
22         thread2.start();
23
24         System.out.println("火箭发射倒计时:");
25
26
27     }
28
29 }

  运行结果: 

火箭发射倒计时:
$Thread-0(9)
$Thread-0(8)
$Thread-0(7)
$Thread-0(6)
$Thread-0(5)
$Thread-0(4)
$Thread-0(3)
$Thread-0(2)
$Thread-0(1)
$Thread-0(0)
$Thread-1(9)
$Thread-1(8)
$Thread-1(7)
$Thread-1(6)
$Thread-1(5)
$Thread-1(4)
$Thread-1(3)
$Thread-1(2)
$Thread-1(1)
$Thread-1(0)

一个线程等待另一个线程结束后再执行:当执行PrintNum这个任务时,打印到数字50时,转而去执行打印字符C这个任务,知道线程thread4执行完才继续执行打印数字任务。

 1 package com.muzeet.testThread;
 2
 3 public class PrintNum implements Runnable {
 4
 5     private int lastNum;
 6
 7     public PrintNum(int n)
 8     {
 9         lastNum = n;
10     }
11
12     @Override
13     public void run() {
14         // TODO Auto-generated method stub
15         Thread thread4 = new Thread(new PrintChar('c', 40));
16         thread4.start();
17         try {
18         for(int i=1;i<=lastNum;i++)
19         {
20             System.out.println(" " + i);
21             if(i == 50)
22             {
23
24                     thread4.join();
25
26             }
27         }
28         } catch (InterruptedException e) {
29             // TODO Auto-generated catch block
30             e.printStackTrace();
31         }
32     }
33
34 }

4.两种方法的比较(转载)

首先分析两种方式的输出结果,同样是创建了两个线程,为什么结果不一样呢?

使用实现Runnable接口方式创建线程可以共享同一个目标对象(TreadDemo1 tt=new TreadDemo1();),实现了多个相同线程处理同一份资源。当第一个线程执行完任务后,countDown已经为0,所以第二个线程就不会输出。而继承Thread创建线程的方式,new出了两个任务类对象,有各自的成员变量,相互之间不干扰。

然后再看一段来自JDK的解释:

Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参数方法。

设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议。例如,Thread 类实现了Runnable。激活的意思是说某个线程已启动并且尚未停止。

此外,Runnable 为非 Thread 子类的类提供了一种激活方式。通过实例化某个Thread 实例并将自身作为运行目标,就可以运行实现Runnable 的类。大多数情况下,如果只想重写run() 方法,而不重写其他 Thread 方法,那么应使用Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。(推荐使用创建任务类,并实现Runnable接口,而不是继承Thread类)

采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。

 

转载于:https://www.cnblogs.com/muzeet/p/4338973.html

java多线程总结一:线程的两种创建方式及比较相关推荐

  1. java多线程总结一:线程的两种创建方式及优劣比较

    1.通过实现Runnable接口线程创建 (1).定义一个类实现Runnable接口,重写接口中的run()方法.在run()方法中加入具体的任务代码或处理逻辑. (2).创建Runnable接口实现 ...

  2. 【无标题】单例模式的两种创建方式:饿汉式和懒汉式

    这里写自定义目录标题 单例模式的两种创建方式:饿汉式和懒汉式 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂 ...

  3. 线程的三种创建方式和他们的优缺点

    文章目录 一.线程的三种创建方式 1.继承Thread 2.实现Runable接口 3.实现Callable接口 二.三种创建方式的优缺点 1.使用Runnable接口比使用继承Thread的优势 2 ...

  4. Java线程的两种实现方式

    前言 线程是程序的一条执行线索,执行路径,是程序使用cpu的最小单位.线程本身不能运行,它只能运行在程序中,线程是依赖于程序存在的. 多线程的意义 其实任何一个程序的执行都需要获得cpu的执行权,是由 ...

  5. eclipse让实现类也添加上接口的注释_多线程:面试常问的两种创建方式,数据共享实现和正确停止线程...

    多线程 进程与线程的区别: 进程:程序的执行过程,持有资源(内存)(共享内存和文件)和线程.比如,电脑上的eclipse.QQ.微信等运行中的软件就是一个进程 线程应用:1.eclipse编辑代码时, ...

  6. java中字符串的创建_【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

  7. 初始化一个java空数组_Java 数组的两种初始化方式

    一.数组 1.数组中存储元素的类型是统一的,每一个元素在内存中所占用的空间大小是相同的,知道数组的首元素的内存地址,要查找的元素只要知道下标,就可以快速的计算出偏移量,通过首元素内存地址加上偏移量,就 ...

  8. java匿名内部类_java中匿名内部类的两种实现方式

    使用匿名内部类课使代码更加简洁.紧凑,模块化程度更高.内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到.然而这个不是我说的重点,我说的很简单,就是匿名内部类的两种实现方式 ...

  9. 线程的三种创建方式以及代码实现

    线程和进程的概念 一个进程可以有多个线程 程序:是指令和数据的有序集合(静态的) 进程:是执行程序的一次执行过程(动态的),是系统资源分配的单位.在操作系统中运行的程序就是进程. 通常在一个进程中可以 ...

最新文章

  1. V4L2获取usb视频流测试代码
  2. 基于感知损失的实时风格迁移与超分辨率重建
  3. POJ-1664 放苹果
  4. clion 代码格式化 大括号换行对齐
  5. 朱晔的互联网架构实践心得S1E3:相辅相成的存储五件套
  6. Java排序算法之——希尔排序
  7. 面向对象八大设计原则
  8. 推荐几个出论文的好方向!!
  9. mysql数据库表的类型介绍,mysql数据库表的类型介绍
  10. 比较两个对象是否一样的代码
  11. pyton random 模块
  12. 电脑版美食大战老鼠放置html,美食大战老鼠电脑版
  13. MMORPG端游《ELYON》12月10日上线 采用买断式收费方式
  14. js小学生图区_多种方式实现js图片预览
  15. java.util.concurrent.TimeoutException: Waited 3000 milliseconds (plus 2 milliseconds, 351400 nanosec
  16. HDU 3236 Gift Hunting (程序猿的哄女朋友方式)
  17. Python数据分析与展示教程(北理工 嵩天教授)——展示数据基本方法
  18. 别让职场形象毁了你的职场前程
  19. 移动端flexible解决ipad和ipad Pro不适配
  20. LSTM对比Bi-LSTM的电力负荷时间序列预测(Matlab)

热门文章

  1. adb shell 是这个啥东东
  2. 使用NHibernate, Oracle Clob/NClob无法插入
  3. visual studio 删除附加项
  4. mysql 表变量_在MySQL中创建表变量
  5. 重新配对_国羽世界冠军组合重新配对!男方笑言“老夫老妻”,没什么感觉
  6. 鼠标悬停显示图片html5,JavaScript 鼠标悬停图片,显示隐藏文本
  7. java ftp连接成功 上传失败_ftp自动上传工具,如何设置及配置ftp自动上传工具
  8. hssfwork 导出excel 文件已损坏_C# NPOI 操作EXCEL文件的读取和导出
  9. 数据接口请求异常:error_springboot2.2.X手册:构建多元化的API接口,我们这样子设计
  10. c语言中memset_C中的memset()