线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
下图显示了一个线程完整的生命周期。
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
- public class MyRunnable implements Runnable{
- private String msg;
- @Override
- public void run() {
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+"\t"+this.msg);
- }
-
- }
- public MyRunnable(){
- super();
- }
- public MyRunnable(String msg){
- super();
- this.msg=msg;
- }
- }
- /**
- * 使用Runnable目的就是有共享内容 几个线程共同完成任务
- * @author WQY
- *匿名内部类在Runnable上的使用
- *不能加参数 必须无参!如果线程只在一处使用,可以选择这种方式,但是可读性较差
- */
- //
- public class Test3 {
- public static void main(String[] args) {
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+"但可寻所爱");
- }
- MyRunnable m1=new MyRunnable("山海不可平");
- //1.使用匿名内部类(很少使用)
- Thread t1=new Thread(new Runnable() {
-
- @Override
- public void run() {
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+"山海不可平");
- }
-
- }
- },"所思隔云端");
- //2.没有使用匿名内部类,实现Runnable接口解决了单一继承限制
- Thread t2=new Thread(m1,"奈何凡肉身");
- t1.start();
- t2.start();
- }
- }
- public class MyThread extends Thread {
- private String msg;
- public MyThread() {
- super();
- }
- public MyThread(String name,String msg) {
- super(name);
- this.msg=msg;
- }
- @Override
- public void run() {
- for(int i=0;i<10;i++){
- System.out.println(this.getName()+"\t"+this.msg);
- }
- }
- }
- //主线程 默认名字main
- public class Test2 {
- public static void main(String[] args) {
- //MyThread mt1=new MyThread("mt1","一望可相见");
- MyThread mt2=new MyThread("mt2","一步如重城");
- //使用匿名内部类来启动线程
- new Thread("mt1"){
- @Override
- public void run() {
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+"\t"+"一望可相见");
- }
- }
- }.start();
- //继承Thread建立线程
- mt2.start();
- for(int i=0;i<10;i++){
- System.out.println(Thread.currentThread().getName()+"\t"+"所爱隔山海");
- }
- }
- }
- class TicketRunnable implements Runnable {
- private Integer count;
- public TicketRunnable(Integer count) {
- super();
- this.count = count;
- }
- public TicketRunnable() {
- super();
- }
- @Override
- public void run() {
- while(true){
- //锁池状态
- //同步块 (同步锁)解决脏数据问题。保证一个线程在运行 运行结束别的线程才能进去
- synchronized(this){//this是表示当前对象 共享的count 。synchronized目的就是把共享的数据锁住
- if(count<=0){
- System.out.println(Thread.currentThread().getName()+"exit 窗口:\t"+this.count);
- break;
- }
- try {
- //sleep()控制运行时间
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- int i=count--;
- //count-- 表达式的值后改变 先给表达式赋值在改count的值
- System.out.println(Thread.currentThread().getName()+"窗口:\t"+i);
- }
- }
- }
-
- }
- public class Ticket {
- public static void main(String[] args) {
- MyThreadDemo m=new MyThreadDemo();
- Thread t1=new Thread(m,"窗口1");
- Thread t2=new Thread(m,"窗口2");
- Thread t3=new Thread(m,"窗口3");
- Thread t4=new Thread(m,"窗口4");
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
- public class Warehouse {
- private List<String> goods=new ArrayList<String>();
- public Warehouse() {
- super();
- }
- public Warehouse(List<String> goods) {
- super();
- this.goods = goods;
- }
- public List<String> getGoods() {
- return goods;
- }
- public void setGoods(List<String> goods) {
- this.goods = goods;
- }
- //同步方法 使用wait() 和notifyAll() 必须在同步里
- public synchronized void customer(){
- if(this.goods.isEmpty()){
- System.out.println("仓库空了");
- try {
- this.wait();//进入等待状态 退出CPU 方法结束,不向下运行
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- /*try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }*/
- System.out.println("消费者消费了"+this.goods.remove(0));
- this.notifyAll();
- }
- public synchronized void produce(String name){
- if(!this.goods.isEmpty()){
- System.out.println("仓库满了");
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- /*try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }*/
- this.goods.add(name);
- System.out.println("生产者生产了" + name);
- this.notifyAll();
- }
- }
- //生产者
- public class Pro implements Runnable {
- private Warehouse w;
- public Pro() {
- super();
- }
- public Pro(Warehouse w) {
- super();
- this.w = w;
- }
- @Override
- public void run() {
- for(int i=0;i<1000;i++){
- this.w.produce("产品"+(i+1));
- }
- }
- }
- //消费者
- public class Cus implements Runnable {
- private Warehouse w;
- public Cus() {
- super();
- }
- public Cus(Warehouse w) {
- super();
- this.w = w;
- }
- @Override
- public void run() {
- for(int i=0;i<1000;i++){
- this.w.customer();
- }
- }
- }
- //测试
- public class TestCP {
- public static void main(String[] args) {
- Warehouse w=new Warehouse();
- Pro p=new Pro(w);
- Thread tp=new Thread(p);
- Cus c=new Cus(w);
- Thread tc=new Thread(c);
-
- tp.start();
- tc.start();
- }
- }
线程的一些问题:每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。
Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
Java 提供了三种创建线程的方法:
创建一个线程,最简单的方法是创建一个实现 Runnable 接口的类。
为了实现 Runnable,一个类只需要执行一个方法调用 run(),声明如下:
你可以重写该方法,重要的是理解的 run() 可以调用其他方法,使用其他类,并声明变量,就像主线程一样。
在创建一个实现 Runnable 接口的类之后,你可以在类中实例化一个线程对象。
Thread 定义了几个构造方法,下面的这个是我们经常使用的:
这里,threadOb 是一个实现 Runnable 接口的类的实例,并且 threadName 指定新线程的名字。
新线程创建之后,你调用它的 start() 方法它才会运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号