Java并发-多线程(1)

一、进程和线程的概念

1.进程和线程概念

每个运行的程序就是一个进程。程序进行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程。

进程间有独立的内存资源,而线程是共享父进程的全部资源。线程间是抢占式的运行,即并发性

 

2. 多线程是并发性而不是并行性的

并发:在时间片间相互切换。

并行:同时运行。

所以,多线程的意义在于最大限度的使用CPU

 

二、线程的创建与启动

1.实现方法一:继承Thread类创建线程

第一步:继承Tread类

第二步:重写run()方法。

第三步:在主线程里面开启子线程

核心代码:new SonThread().start();

public class ThreadDemo {

      // 主线程

      public static void main(String[] args) {

           // 第三步:在主线程中调用start()启动

           SonThread sonThread = new SonThread();

           sonThread.start();

           //sonThread.run(); // 错误的用法

          

           System.out.println("after thread");

      }

     

      // 子线程类

      // 第一步:继承Thread类

      public static class SonThread extends Thread {

           // 第二步:重写run方法

           @Override

           public void run() {

                 // things need todo

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

                      System.out.println("something need long time");

                 }

           }

      }

}

 

2.实现方法二:实现Runnable接口

第一步:定义一个类,实现Runnable接口。

第二步:在类里面实现run()方法。

第三步: 在主线程里创建子线程对象。

第四步:创建新的Thread对象,将类对象传入Thread构造方法。

第五步:新的对象启动start()方法。

其实和第一种方式一一样,都是都是new Thread().start()。

核心代码:

new Thread(new Runnable() {

@Override

        public void run() {

             // do something

}

}).start();

 

3.两种方式的比较

使用Thread类的缺点:由于Java的点继承,该类会无法再继承其他类。(不过多数情况下也不需要再继承其他类。)

Runnable的优势:可以让多个线程共享同一个Runnable对象,很适合多个线程来处理同一份资源的情况,即同一个runnable对象作为参数传入多个Thread的构造方法

其实两种方式的本质都是new Thread().start()启动线程,不过一个是直接重写run()方法,一个是用runnable对象从构造方法传入。

一般推荐用Runnable方法。

 

三、线程常用的基本方法

getName():获得当前线程的名称。

static Tread.currentThread():获得当前执行的线程对象。

start():让线程进入就绪状态。

boolean isAlive():判断线程是否处于活动状态。

void setName(String name); 设置线程的名称

 

四、线程的生命周期

新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、死亡(Dead)

1.新建(New)

仅仅由Java虚拟机分配了内存,并初始化其成员变量的值。这个时候线程对象还没有表现出线程的动态特征,线程体也不会被执行。

 

2.就绪(Runnable)

线程的run方法体并不会立刻执行,只是告诉程序该线程可以运行了。至于何时运行,则取决于JVM的线程调度器的调度。

 

3.运行(Running)

处于就绪状态的线程获得了CPU,则该线程会开始执行run()方法内的线程执行体,此时线程进入了运行状态。线程调度取决于底层平台所采用的策略。

 

4.阻塞(Blocked)

a.何为阻塞

当一个运行状态下线程除了被强制中断以外,还有可能被阻塞,从而进入到阻塞状态,进入阻塞状态后,其他线程就可以获得执行的机会。被阻塞的线程在合适的时候会解除阻塞,从而再次进入就绪状态(不是运行状态),等待线程调度器再次调度它。

b.引起阻塞的情况

线程调用sleep()方法主动放弃所占用的处理器资源。

线程调用一个阻塞式的IO方法,在该方法返回之前,线程被阻塞。

线程视图获得一个同步监视器,但该同步监视器正被其他线程所持有。即等待其他线程完毕。

线程在等待某个通知。

调用了线程suspend()方法将该线程挂起,但是这个方法容易引起死锁,所以不推荐使用,已过时

c.线程的结束阻塞

调用sleep()方法的线程经过了指定的时间

线程调用的阻塞式IO方法已经返回

线程成功地获得了视图取得的同步监视器

线程正在等待某个通知时,其他线程发出了一个通知

处于挂起状态的线程被调用了resume()恢复方法(不推荐使用suspend()方法将该线程挂起)

 

5.死亡(Dead)

线程结束后,就会进入死亡状态。

 

6.注意

1)可以通过isAlive()方法来判断当前线程的状态,

如果线程处于就绪、运行、阻塞状态,该方法返回true;

如果处于新建、死亡状态,该方法返回false;

 

2)只能对新建状态的线程调用start()方法,只能调用一次。不是调用run()方法。

 

五、线程的控制

1.join方法

当某个线程A调用了其他线程B的join()方法时,那么线程A将被阻塞,直到线程B执行完毕后,线程A才重新进入就绪状态

 

if (i = 100) {

        otherThread.join();  // 开始执行otherThread线程,直到执行完毕,才会继续执行自己。

}

 

2.后台线程

在启动一条线程前,可以通过setDaemon(true);方法,设置该线程为后台线程,又称为守护线程,JVM的垃圾回收线程就是典型的后台线程。

如果前台线程全部死亡,则后台线程也会自动死亡,后台线程不再继续执行

 

public static void main(String[] args) {

AThread s = new Thread();

s.setDaemon(true); // 将该线程设置为后台线程

s.setName(“彦祖的线程”); // main()死掉后,s就自行了结

s.start();

}

 

通常开启的线程默认都是前台线程,后台线程开启的子线程默认是后台线程

setDaemon()方法必须在start()之前调用

 

3.sleep()方法

该方法可以使当前正在执行的线程暂定一段时间,进入阻塞状态。sleep()方法有一个参数,用来设置线程暂停多少毫秒,经过指定时间后,线程重新进入就绪状态

处于sleep()休眠中的线程不会被执行,即便当前没有任何线程在执行,该线程也不会执行

 

4.yield方法(放弃)

(少用)

让当前正在执行的线程暂停,但是不会阻塞该线程,而是直接将该线程转入到就绪状态。

但可能刚yield完,调度器又调用了该线程。

当某个线程调用了yield()方法暂停后,只有优先级大于等于该线程的,并且处于就绪状态的线程才会获得执行的机会。

 

5.线程的优先级

每个线程执行时都具有一定的优先级,优先级高的线程可能会比优先级低的线程获得更多的执行机会

Thread类提供了setPriority(int newPriority);方法来设置线程的优先级,范围是1-10,数字越大优先级越高。

另外Thread还提供了三个常量来表示优先级,推荐用这种方式设置,因为有的操作系统优先级最高可能不是10,而是7,或是其他:

MAX_PRIORITY:其值是10。

NORM_PRIORITY:其值是5。

MIN_PRIORITY:其值是1。

每个线程的优先级默认都和创建它的父线程优先级相同

其实线程优先级一般也不太靠谱,因为不能确实的保证最先执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值