Java基础教程——线程状态

线程状态

JAVA定义了6种线程状态:

Thread.State
    public enum State {
        NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;
    }

分别是:

  • 新建状态·NEW
  • 运行状态·RUNNABLE
  • 阻塞状态·BLOCKED
  • 无限等待状态·WAITING
  • 休眠状态·TIMED_WAITING
  • 死亡状态·TERMINATED

线程不可能一直运行,除非瞬间执行结束。

为了给其他线程执行的机会,正在执行的线程会被中断。线程调度的细节取决于操作系统:

|--现代桌面操作系统和服务器操作系统采用抢占式调度策略,给每个线程一个时间段,时间到了就换其他线程执行,在选择下一线程时会考虑优先级。
|--手机等小型设备可能采用协作式调度策略,需要线程主动放弃占用的资源。


sleep

【运行】→sleep()→【休眠】

public class TestSleep {
    public static void main(String[] args) {
        // 获得当前运行的线程
        Thread tMain = Thread.currentThread();
        System.out.println("当前运行的线程是:" + tMain.toString());
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
            try {
                // 使当前线程休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("END");
    }
}

示例:显示时间
一个时间每秒更新,一个时间三秒更新(使用到了GUI)

这个示例用到了JAVA的图形界面编程,必须要继承JLabel类,因此无法继承Thread类,这也体现了Runnable接口的优点。

import java.awt.*;
import java.util.*;
import javax.swing.*;
public class 每秒更新 {
    public static void main(String[] args) {
        JFrame form1 = new JFrame();
        form1.setBounds(300, 300, 350, 100);
        form1.setVisible(true);
        Container cp = form1.getContentPane();
        cp.setLayout(new GridLayout(2, 1));
        cp.add(new ShowDateLabel(1000));
        cp.add(new ShowDateLabel(3000));
    }
}
class ShowDateLabel extends JLabel implements Runnable {
    private int sleepTime; // 休眠时间
    public ShowDateLabel(int sleepTime) {
        this.sleepTime = sleepTime;
        // 启动线程
        new Thread(this).start();
    }
    public void run() {
        try {
            while (true) {
                // 显示当前时间
                this.setText(new Date().toString());
                Thread.sleep(sleepTime);
            }
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
}

interrupt

中断线程,属于异常,尽量不用

import java.util.Date;
public class SleepInterrupt {
    public static void main(String[] args) {
        SleepThread thread = new SleepThread();
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        thread.interrupt();
    }
}
class SleepThread extends Thread {
    boolean flag = true;
    public void run() {
        while (flag) {
            System.out.println("===" + new Date() + "===");
            try {
                sleep(10000);
            } catch (InterruptedException e) {
                System.out.println("===Sleep被吵醒===");
                return;
            }
        }
    }
}

yield(礼不下庶人)

yield:屈服,退让

暂停当前正在执行的线程对象,并执行其他线程。
有机会被执行的是优先级相同或更高的线程,被yield的线程有可能被重新执行。

public class TestYield {
    public static void main(String[] args) {
        ThreadTestYield t1 = new ThreadTestYield("t1");
        ThreadTestYield t2 = new ThreadTestYield("   t2");
        // 如果t2优先级较低:yield时t1不让t2;sleep(100)时会让
        // t2.setPriority(Thread.MAX_PRIORITY);
        t1.start();
        t2.start();
    }
}
class ThreadTestYield extends Thread {
    ThreadTestYield(String s) {
        super(s);
    }
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (i % 10 == 0) {
                System.out.println(getName() + ": " + i + ": yield");
                yield();
            } else {
                System.out.println(getName() + ": " + i);
            }
        }
    }
}

join(等你做完)

join方法用于“等待线程终止”。

package ahjava.p06thread;
public class _31TestJoin {
    public static void main(String[] args) {
        MyThread2 t1 = new MyThread2("abcde");
        t1.start();
        try {
            t1.join();// 等子线程先运行
        } catch (InterruptedException e) {
        }
        for (int i = 1; i <= 10; i++) {
            System.out.println("i am main thread");
        }
    }
}
class MyThread2 extends Thread {
    MyThread2(String s) {
        super(s);
    }
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("i am " + getName());
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}

后台线程

线程分为前台线程、后台线程。

前台线程也叫用户线程
后台线程也叫守护线程
JVM的垃圾回收线程就是后台线程。

通过设置thread.setDaemon(true)可以把线程设为后台线程。但是需要在线程启动之前设置。

deamon本是守护神的意思。

前台线程在主线程结束后也要执行完才结束;
后台线程会在前台线程都结束之后自动结束,不会等自己执行完毕。
默认情况下,由前台线程创建的线程仍是前台线程,由后台线程创建的线程仍是后台线程。

public class TestDaemonThread extends Thread {
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(getName() + "  " + i);
        }
        System.out.println("-----子线程结束-----");
    }
    public static void main(String[] args) {
        TestDaemonThread t = new TestDaemonThread();
        // 设为后台线程,不会看到“子线程结束”语句的输出
        t.setDaemon(true);
        t.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "  " + i);
        }
        System.out.println("=====main线程结束=====");
    }
}

原文地址:https://www.cnblogs.com/tigerlion/p/11179237.html

时间: 2024-08-01 18:13:54

Java基础教程——线程状态的相关文章

Java基础教程——线程池

启动新线程,需要和操作系统进行交互,成本比较高. 使用线程池可以提高性能-- 线程池会提前创建大量的空闲线程,随时待命执行线程任务.在执行完了一个任务之后,线程会回到空闲状态,等待执行下一个任务.(这个任务,就是Runnable的run()方法,或Callable的call()方法). Java 5之前需要手动实现线程池,Java 5之后直接支持线程池. Java.util.concurrent. Executors:用于创建线程池 |--|--Executors.newFixedThreadP

Java基础教程——线程同步

线程同步 synchronized:同步的 例:取钱 不做线程同步的场合,假设骗子和户主同时取钱,可能出现这种情况: [骗子]取款2000:账户余额1000 [户主]取款2000:账户余额1000 结果是社会财富增加1000,银行不开心. 代码如下所示: // 账户类 class Account { private int accountBalance = 2000; public void withdraw(String userName, int amount) { System.out.p

Java基础教程:多线程基础(2)——线程间的通信

Java基础教程:多线程基础(2)--线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 思维导图 等待中 等待/通知机制 不使用等待/通知机制 我们可以使用使用sleep()与 whle(true) 死循环来实现多个线程间的通信. 虽然两个线程实现了通信,但是线程B必须不断的通过while语句轮训机制来检测某一个条件,这样会浪费CPU资源. 如果轮询间隔较小,更浪费时间间隔.如果轮训

Java基础教程:JDBC编程

Java基础教程:JDBC编程 快速开始 什么是JDBC JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库. JDBC API 库包含下面提到的每个任务,都是与数据库相关的常用用法. 制作到数据库的连接. 创建 SQL 或 MySQL 语句. 执行 SQL 或 MySQL 查询数据库. 查看和修改所产生的记录. 从根本上来说,JDBC 是一种规范,它提供了一套完整的接口,允许便携式访问到底层数据库,因此可以用 J

Java基础教程:HashTable与HashMap比较

Java基础教程:HashTable与HashMap比较 1.  关于HashMap的一些说法: a)  HashMap实际上是一个"链表散列"的数据结构,即数组和链表的结合体.HashMap的底层结构是一个数组,数组中的每一项是一条链表. b)  HashMap的实例有俩个参数影响其性能: "初始容量" 和 装填因子. c)  HashMap实现不同步,线程不安全.  HashTable线程安全 d)  HashMap中的key-value都是存储在Entry中的

Java基础教程:内部类

Java基础教程:内部类 内部类 内部类,是指在一个类的内部定义的类.就像下面这样: public class EnclosingClass {   . . .   public class NestedClass {   . . .     } } 内部类拥有访问外部类所有元素(包括private.static)的访问权.当某个外部类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用.然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员. 内部类

Java基础教程 - 组合

1. 什么是组合? 如果一个类的对象和另一个类满足"has-a"关系的话,我们就可以在一个类中,把另一个类的对象作为其对象成员. 什么是"has-a"关系,举个例子:现在有一个类LapTop.class,还有一个是Moniter.class.好显然,Laptop "has-a" Moniter,也就是说,他们是满足"has-a"关系的.这时候,我们就可以把Moniter作为Laptop的一个数据成员. class Laptop

Java中的线程状态转换和线程控制常用方法

Java 中的线程状态转换: [注]:不是 start 之后就立刻开始执行, 只是就绪了(CPU 可能正在运行其他的线程). [注]:只有被 CPU 调度之后,线程才开始执行, 当 CPU 分配给你的时间片到了, 又回到就绪状态, 继续排队等候. 线程控制的基本方法: isAlive(): 判断线程是否还活着, start 之后,终止之前都是活的; getPriority(): 获得线程的优先级数值; setPriority(): 设置线程的优先级数值(线程室友优先级别的);   Thread.

(CZ深入浅出Java基础)线程笔记

一.线程的引入 1.多线程概述 1.1.进程 a.正在运行的程序,是系统进行资源分类和调用的独立单位. b.每个进程都有它自己的内存空间和系统资源. 1.2.线程 a.是进程中的单个顺序控制流,是一条执行路径. b.一个进程如果只有一条路径,则称为单线程程序. c.一个进程如果有多条执行路径,则称为多线程程序. 1.3.小结 线程多的进程抢到CPU执行权的概率大,但是仍具有随机性. 2.Java程序运行原理 2.1.Java运行 Java命令会启动Java虚拟机,启动JVM,等于启动了一个应用程