[02] 线程的创建和常用方法

1、线程的创建

线程的创建可以通过两种方式,第一种是 Thread类,第二种是 Runnable接口:

  • 继承 Thread 类,覆盖 run()
  • 实现 Runnable 接口,实现 run()

然后线程的启用是通过 start() 方法,它会自动调用 run() 方法,如下例:

//继承Thread
public class MyThread extends Thread {
    @Override
    public void run() {
        for(int i = 0; i < 100; i++) {
            System.out.println("MyThread:" + i);
        }
    }
}

//实现Runnable
public class MyRunnableImpl implements Runnable {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("MyRunnableImpl:" + i);
        }
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        Thread thread1 = new MyThread();
        Thread thread2 = new Thread(new MyRunnableImpl());
        thread1.start();
        thread2.start();
    }
}

//输出结果示例
...
MyThread:23
MyThread:24
MyThread:25
MyRunnableImpl:0
MyThread:26
MyRunnableImpl:1
MyThread:27
MyRunnableImpl:2
...

40

1

//继承Thread

2

public class MyThread extends Thread {

3

    @Override

4

    public void run() {

5

        for(int i = 0; i < 100; i++) {

6

            System.out.println("MyThread:" + i);

7

        }

8

    }

9

}

10


11

//实现Runnable

12

public class MyRunnableImpl implements Runnable {

13

    public void run() {

14

        for (int i = 0; i < 100; i++) {

15

            System.out.println("MyRunnableImpl:" + i);

16

        }

17

    }

18

}

19


20

//测试类

21

public class Test {

22

    public static void main(String[] args) {

23

        Thread thread1 = new MyThread();

24

        Thread thread2 = new Thread(new MyRunnableImpl());

25

        thread1.start();

26

        thread2.start();

27

    }

28

}

29


30

//输出结果示例

31

...

32

MyThread:23

33

MyThread:24

34

MyThread:25

35

MyRunnableImpl:0

36

MyThread:26

37

MyRunnableImpl:1

38

MyThread:27

39

MyRunnableImpl:2

40

...

可以看到,线程的运行是并行的,而不是先执行完整个 thread1 的 start() 再执行 thread2 的 start()

另外,Runnable 接口的存在主要是为了解决 Java 中不允许多继承的问题,所以我们往往通过实现 Runnable 接口,然后再将其封装到一个 Thread 类中使用(如上例 Thread thread2 = new Thread(new MyRunnableImpl()); )

事实上,我们也可以通过匿名内部类的方式,快速实现线程,如上可以修改为:

public class Test {
    public static void main(String[] args) {
        //Thread
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("anonymous thread:" + i);
                }
            }
        };
        //Runnable
        Thread thread2 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("anonymous runnable:" + i);
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

x

1

public class Test {

2

    public static void main(String[] args) {

3

        //Thread

4

        Thread thread1 = new Thread() {

5

            @Override

6

            public void run() {

7

                for (int i = 0; i < 100; i++) {

8

                    System.out.println("anonymous thread:" + i);

9

                }

10

            }

11

        };

12

        //Runnable

13

        Thread thread2 = new Thread(new Runnable() {

14

            public void run() {

15

                for (int i = 0; i < 100; i++) {

16

                    System.out.println("anonymous runnable:" + i);

17

                }

18

            }

19

        });

20


21

        thread1.start();

22

        thread2.start();

23

    }

24

}

2、线程的常用方法

2.1 线程的生命周期

要说到线程的常用方法,首先就要先了解一个线程的生命周期,如下图:

  • 新建状态:使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程
  • 就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中(排队状态),要等待JVM里线程调度器的调度
  • 运行状态:如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态
  • 阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。阻塞又可以分为三种:
    • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态
    • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)
    • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态
  • 死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态

2.2 线程的常用方法

2.2.1 start、run

基于线程的生命周期,那么 start() 和 run() 方法想必也就不用多说了:

  • start()  启动线程,进入就绪状态(万事俱备,只欠CPU)
  • run()    运行状态,执行操作

2.2.2 sleep

sleep() 用于使线程进入阻塞状态,强制当前正在执行的线程休眠,计时到后返回到就绪状态。它是Thread类的静态方法:

  • Thread.sleep(long millis)    休眠 ${millis} 毫秒
  • Thread.sleep(long millis, int nanos)    休眠 ${millis} 毫秒 + ${nanos} 纳秒

注意:休眠完成之后进入的是就绪状态,等待进入运行状态,这意味着 "休眠 --> 执行" 的过程会大于 sleep 方法设置的值,因为实际上还要算上就绪状态的排队时间,即真正过程是 "休眠 --> 就绪 --> 执行"

另外,sleep() 是 Thread 的静态方法,调用的是当前运行的线程,所以要保证某个线程的休眠,应将 sleep() 的调用放在线程的 run() 之中

2.2.3 yield

Thread.yield() 的作用是,暂停当前正在执行的线程,并让其回到就绪状态,以允许具有相同优先级的其他线程获得运行机会。但是,实际中无法保证 yield() 达到让步的目的,因为让步的线程在就绪状态仍可能被再次选中执行。

注意:yield() 只是将线程转到就绪状态,而不会进入阻塞状态。

2.2.4 join

join(long millis) 方法的作用是让某个线程 "霸占" 资源一段时间,如两个线程交互运行,如果 thread2.join(5000),那么 thread2 将强制霸占执行 5s,之后其他线程才有使用的机会。

2.2.5 setPriority

setPriority(int newPriority) 方法用于设置线程的优先级别,数值越高表示优先级越高。优先级的范围在 1 - 10 之间,默认为5

每个线程具有各自的优先级,线程的优先级表示该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定优先使哪个线程进入运行状态。但这并不意味着低优先级的线程得不到运行,只是运行的几率比较小,如垃圾回收机制线程的优先级就比较低。另外:

  • 线程优先级具有继承性,如A线程启动B线程,则B线程的优先级和A一样
  • 线程优先级具有随机性,即线程优先级高的不一定每次都先执行

2.3 守护线程

多线程分类

  • 用户线程:运行在前台,执行具体的任务,如程序的主线程,用户自己创建的线程
  • 守护线程:运行在后台,为其他前台线程服务(守护)

它们的区别在于 "前台线程保证完成,守护线程不保证完成":

  • 前台线程完成了之后,虚拟机执行的进程才会结束
  • 进程结束之后(此时前台线程已经结束),也会结束后台线程,但是不论后台线程是否已经完成都会将其结束

守护线程的应用如:数据库连接池中的检测线程、JVM启动后的检测线程、垃圾回收线程等

setDaemon(true) 可以将线程设置为守护线程,必须在线程进入就绪状态之前,即必须在 start() 方法调用之前使用。

3、参考链接:

原文地址:https://www.cnblogs.com/deng-cc/p/9461621.html

时间: 2024-10-20 18:32:48

[02] 线程的创建和常用方法的相关文章

Java线程:创建与启动

Java线程:创建与启动 一.定义线程 1.扩展java.lang.Thread类. 此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法:否则,该方法不执行任何操作并返回.   Thread 的子类应该重写该方法. 2.实现java.lang.Runnable接口. void run() 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独

线程的状态和常用方法

线程的状态一个线程从创建,启动到终止的整个过程称为线程的生命周期,在其间的任何时刻,线程总是处于某个特定状态.这些状态如下:新建状态:线程对象已经创建,对应new语句.就绪状态:就绪状态也可叫做可执行状态,对应start()方法.运行状态:当处于就绪的线程被调度并获得了cpu等执行必须的资源时,便进入到该状态,即运行了run()方法.等待/阻碍/睡眠状态:三个状态组合为一种,其共同点是线程仍然是活的,但是当前没有条件运行.换句话说,它是可运行的,如果某个事件出现,它可能返回到可运行状态,对应以下

猫猫学iOS(四十九)多线程网络之线程的创建NSThreand

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 一:NSThread的基本使用 1:创建和启动线程 一个NSThread对象就代表一条线程 创建.启动线程 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(sel) object:nil]; [thread start];

基础学习day11--多线程一线程的创建,运行,同步和锁

1.1.进程和线程 进程:一个应用程序一般都是一个进程,正在进行的程序 每一个进程最少都有一个线程,都有一个执行顺序,该顺序是一个执行路径或者一个控制单元 线程:进程中一个独立的控制单元,线程控制着进程的执行. windows中的任务管理器,可以查看进程,linux下通过ps命令 线程是进程的最小单位 线程依赖于进程 线程随着进程的创建和创建,随着进程的结束而消亡 如迅雷:可以同时开启多个下载,就是多线程 多个程序同时执行,时CPU在很快的切换,看上去是同时执行,实际上是在CPU在切换执行. 多

Java线程的创建和基本使用

线程的创建 1.创建线程的两种方法 (1) 创建Thread的子类,并覆盖run()方法 (2) 实现Runnable接口 创建多线程的方法 方法1:通过创建Thread类的子类实现多线程,步骤如下 : 1. 定义Thread类的一个子类. 2. 定义子类中的方法run( ),覆盖父类中的 方法run( ). 3. 创建该子类的一个线程对象. 4. 通过start( )方法启动线程. 注意: 1.每个线程都将启动,每个线程都将运行直到完成. 2.一系列线程以某种顺序启动并不意味着将按该顺序执行.

C#在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级

首先在form1的窗体载入中新建了一个Class1对象并将本身的引用传递进入其构造函数,然后在Class1的构造函数中创建一个线程.该线程所代理的方法事件是本类中的一个add方法.而add方法的内容则是在form1上放一个textbox.然而这个流程你需要注意的有几个问题:1.哪个是主线程?所谓主线程是第一个启动的线程,是从main开始的.form1的这个窗体是由主线程创建的.2.Thread t的线程是什么?t是由主线程创建的,t的操作内容是在由主线程创建的窗体上放一个textbox.也就是说

Java并发编程:线程的创建

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

iOS-多线程 ,整理集锦,多种线程的创建

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; //创建线程的第一种方式 NSThread *thread = [[NSThread all

java 加入一个线程、创建有响应的用户界面 。 示例代码

javajava 加入一个线程.创建有响应的用户界面 . 示例代码 来自thinking in java 4 21章  部分代码  目录21.2.11 thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155 package org.rui.thread.concurrent; /** * 加入一个线程 * 一个线程可以在其他线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行