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

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

 

时间: 2024-08-29 02:10:32

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

Java---11---多线程的两种创建方式

多线程的两种创建方式: 下面这些东西是API文档中的: public class Thread extends Object implements Runnable 线程 是程序中的执行线程.Java 虚拟机允许应用程序并发地运行多个执行线程. 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程.每个线程都可以或不可以标记为一个守护程序.当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护

线程概述以及线程的两种创建方式

package countThread; public class CountThread extends Thread{ private String name; public CountThread(String name) { super(name); } /** * 线程的执行体 * * 创建新执行线程有两种方法,一种方法是将类声明为Thread的子类,该子类应该重写Thread类中的run方法 * 接下来可以分配并且启动该子类的实例 */ @Override public void r

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

1.通过实现Runnable接口线程创建 (1).定义一个类实现Runnable接口,重写接口中的run()方法.在run()方法中加入具体的任务代码或处理逻辑. (2).创建Runnable接口实现类的对象. (3).创建一个Thread类的对象,需要封装前面Runnable接口实现类的对象.(接口可以实现多继承) (4).调用Thread对象的start()方法,启动线程 示例代码: [java] view plaincopy <span style="font-size:16px;&

Thread -线程的两种创建方式

package cn.learn.thread.Thread; /* 实现Runnable必须重写run()方法,一般推荐用Runnable实现 */ public class RunnableImpl implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()+"执行"); } } package cn.learn.thread.Thre

java中线程的两种创建方式

第一种:继承java.lang.Thread类.然后重写run方法 例如我们模拟一个龟兔赛跑 1 package edu.aeon.thread; 2 3 /** 4 * 说明:模拟龟兔赛跑 5 * 6 * @author lzj 7 * 8 */ 9 public class RabbitThread extends Thread { 10 @Override 11 public void run() { 12 for (int i = 1; i <= 100; i++) { 13 Syste

线程的两种实现方式

线程有两种实现方式 一,Thread类 public class Thread implements Runnable{ } 二,Runnable接口 public interface Runnable{ public abstract void run(); } 区别:Thread是一个类,他继承了runnable接口,而runnable是一个接口, 一个类只能有一个父类,但是可以有多个接口,所以在拓展型方面,ruannale有更好的拓展性,更加灵活 Runnable还可以用于资源共享 1.

String变量的两种创建方式

在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc")://第二种方式 第一种方式创建String变量时,首先查找JVM方法区的字符串常量池是否存在存放"abc"的地址,如果存在,则将该变量指向这个地址,不存在,则在方法区创建一个存放字面值"abc"的地址. 第二种方式创建String变量时,在堆中创建一个存放&q

Java学习(九):Java线程的两种实现方式

线程是程序中一个单一的顺序控制流程.进程内一个相对独立的.可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位.在单个程序中同时运行多个线程完成不同的工作,称为多线程. 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. Java线程创建的两种方式: 1.继承Thread类 public class MyThread extends Thread { private String name;

Java基础之线程的两种实现方式

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程!线程总是属于某个线程,进程中的线程共享进程的内存 注意:对Java来说,run()方法没有任何特别之处.像main()方法一样,它只是新线程知道调用的方法名称(和签名).因此,在Runnable上或者Thread上调用run方法是合法的.但并不启动新的线程,启动新的线程要调用start()方法 在Java中提供了两种方式实现线程:1.继承Thread类 package unit_fifteen; p