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()方法执行完毕,则线程就终止。

  实例代码:

 package com.muzeet.mutithread;

 //每个任务都是Runable接口的一个实例,任务是可运行对象,线程是便于任务执行的对象。必须创建任务类,重写run方法定义任务
public class ThreadDemo1 implements Runnable {
private int countDown = 10;
@Override
//重写run方法,定义任务
public void run() {
while(countDown-- >0)
{
System.out.println("$" + Thread.currentThread().getName()
+ "(" + countDown + ")");
}
}
//调用start方法会启动一个线程,导致任务中的run方法被调用,run方法执行完毕则线程终止 public static void main(String[] args) {
Runnable demo1 = new ThreadDemo1(); Thread thread1 = new Thread(demo1);
Thread thread2 = new Thread(demo1);
thread1.start();
thread2.start(); System.out.println("火箭发射倒计时:"); } }

  程序运行结果:

火箭发射倒计时:
$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()方法,启动一个线程。

  示例代码:

 package com.muzeet.mutithread;

 //每个任务都是Runable接口的一个实例,任务是可运行对象,线程即可运行对象。必须创建任务类,重写run方法定义任务
public class ExtendFromThread extends Thread {
private int countDown = 10;
@Override
//重写run方法,定义任务
public void run() {
while(countDown-- >0)
{
System.out.println("$" + this.getName()
+ "(" + countDown + ")");
}
}
//调用start方法会启动一个线程,导致任务中的run方法被调用,run方法执行完毕则线程终止 public static void main(String[] args) { ExtendFromThread thread1 = new ExtendFromThread();
ExtendFromThread thread2 = new ExtendFromThread();
thread1.start();
thread2.start(); System.out.println("火箭发射倒计时:"); } }

  运行结果: 

火箭发射倒计时:
$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执行完才继续执行打印数字任务。

 package com.muzeet.testThread;

 public class PrintNum implements Runnable {

     private int lastNum;

     public PrintNum(int n)
{
lastNum = n;
} @Override
public void run() {
// TODO Auto-generated method stub
Thread thread4 = new Thread(new PrintChar('c', 40));
thread4.start();
try {
for(int i=1;i<=lastNum;i++)
{
System.out.println(" " + i);
if(i == 50)
{ thread4.join(); }
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

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()方法。

 

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

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

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

  2. 1.java多线程_实现线程的两种方式

    1.java多线程基本知识 1.1.进程介绍 不管是我们开发的应用程序,还是我们运行的其他的应用程序,都需要先把程序安装在本地的硬盘上.然后找到这个程序的启动文件, 启动程序的时候,其实是电脑把当前的 ...

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

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

  4. Thread -线程的两种创建方式

    package cn.learn.thread.Thread; /* 实现Runnable必须重写run()方法,一般推荐用Runnable实现 */ public class RunnableImp ...

  5. [转载]Java线程的两种实现方式

    转载:http://baijiahao.baidu.com/s?id=1602265641578157555&wfr=spider&for=pc 前言 线程是程序的一条执行线索,执行路 ...

  6. 【转载】 Java中String类型的两种创建方式

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

  7. python 多进程的两种创建方式

    Python中使用线程有两种方式:函数或者用类来包装线程对象. 第一种---------函数 菜鸟教程的我没看懂,说说我自己懂的----看视频理解的 import time import thread ...

  8. String变量的两种创建方式

    在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc&qu ...

  9. java中多线程的两种创建方式

    一丶继承Thread类实现多线程 第一步:继承Thread类第二步:重写run()方法第三步:创建继承了Thread类的对象 , 调用start()方法启动. //线程创建方式一 : /* 第一步:继 ...

随机推荐

  1. POI把html写入word doc文件

    直接把Html文本写入到Word文件 获取查看页面的body内容和引用的css文件路径传入到后台. 把对应css文件的内容读取出来. 利用body内容和css文件的内容组成一个标准格式的Html文本. ...

  2. Bootstrap 网格系统(Grid System)

    Bootstrap 网格系统(Grid System) Bootstrap提供了一套响应式,移动设备优先的流式网格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列. 什么是 ...

  3. Spring框架中的aop操作之一 及aspectjweaver.jar与aopalliance-1.0.jar下载地址 包含beans 注解context 和aop的约束

    (aspect oriented programming面向切面编程) 首先在原有的jar包: 需Spring压缩包中的四个核心JAR包 beans .context.core 和expression ...

  4. UVa 167(八皇后)、POJ2258 The Settlers of Catan——记两个简单回溯搜索

    UVa 167 题意:八行八列的棋盘每行每列都要有一个皇后,每个对角线上最多放一个皇后,让你放八个,使摆放位置上的数字加起来最大. 参考:https://blog.csdn.net/xiaoxiede ...

  5. python 发送附件

    #!/usr/bin/env python # encoding: utf-8 #@author: 东哥加油! #@file: sksendmail.py #@time: 2018/8/20 13:3 ...

  6. 对Fiddler设置【Decrypt HTTPS traffic】后火狐浏览器打开https【您的连接并不安全】的解决方法

    火狐浏览器在打开https页面的时候出现[您的连接并不安全]的提示页面: 在设置Fiddler的HTTPS解密的时候,会对下面图中的红线框的选项点击一次生成一个Fiddler 根证书在桌面上: 点击火 ...

  7. ajax实现上传图片保存到后台并读取

    上传图片有两种方式: 1.fileReader  可以把图片解析成base64码的格式,简单粗暴 2.canvas  可以重新绘制一张图片,可以先把获取得到的图片的blob放进canvas里面,再生成 ...

  8. 【实验吧】Once More&&【笔记】 PHP 函数漏洞总结

    <?php if (isset ($_GET['password'])) { if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) = ...

  9. PAT Basic 1055

    1055 集体照 拍集体照时队形很重要,这里对给定的 N 个人 K 排的队形设计排队规则如下: 每排人数为 N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排任何人矮: 每排 ...

  10. BZOJ 1831: [AHOI2008]逆序对

    题目大意: 给出一个序列,有几个位置上的数字任意.求最小的逆序对数. 题解: 自己决定放置的数一定是单调不降的.不然把任意两个交换一下就能证明一定会增加逆序对. 然后就可以DP了,f[i][j]表示第 ...