好久没法推文了,因为这次疫情的原因,小编也是没能去上学,已经待在家好一阵了,一直想写下推文,但是不知道些什么,看了看之前的板块,我打算先把砌砖系列先完善一下,所以今天先和大家回顾一下Java多线程的一些基础知识,并演示一下我写的一些程序。
多线程部分我打算分两个部分:第一部分介绍多线程的基本概念及线程如何构造,第二部分我们介绍多线程之间存在的问题及处理方式。
接下来,我们进入今天的正题–多线程的基本概念及线程如何构造
说到多线程,不得不先说下多进程,进程和线程虽一字之差,但是是不同的概念。我们先给出进程和线程的定义,再详细分析二者的区别与联系。
进程是一个程序关于某个数据集合的一次执行过程,是操作系统进行资源的分配和保护的基本单位。
线程是进程中能够独立执行的实体,是处理器调度和分派的基本单位。线程是进程的组成部分,每个进程允许包含多个并发执行的线程。同一个线程的所有线程共享进程进程所获得的内存空间和资源,但不拥有资源。
从定义中看,进程包括的范围比线程更大,一个进程可以包含许多个并发执行的线程,也就是说,CPU每时刻执行一个进程的时候,其实就是在调度和处理该进程中并发执行的线程。
线程有五种状态:新建、就绪、运行、阻塞、终止。线程创建后处于就绪态,获得处理器时处于运行态,运行中因等待条件处于阻塞态。
关于线程的调度,由于任意时刻只能有一个线程能够占用处理器运行,当有多个线程处于就绪态时,它们排队等待处理资源。因此,需要进行线程调度。线程调度采用的是剥夺方式,剥夺方式主要有两个原则:一是高优先级线程可以剥夺低优先级线程运行,线程的优先级描述线程执行的优先程度。二是当运行线程时间使用完后被剥夺处理器。这种线程调度原则(剥夺式原则)可以避免一个线程长时间独占处理器,给线程提供较好的服务。
下面我们说一下在java中多线程的构造方法。
Java中构造多线程的方法主要有两种:Runnable接口和Thread类,其中Runnable接口约定线程的执行方法(即run()方法),Thread类提供创建、管理和控制线程对象的方法。
下面是Runnable接口和Thread类的局部方法声明:
Runnable接口:
public interface Runnable{
public abstract void run();//描述线程操作的线程体
}
Thread类
Thread类:
public class Thread extends Object implements Runnable{
public Thread();
public Thread(String name);
public Thread(Runnable target);
public Thread(Runnable target, String name);//指定线程名及目标对象
public abstract void run();//描述线程操作的线程体
public final String getName();//返回线程名
public final void setName(String name);
public static int activeCount();//返回当前活动线程数目
public static Thread currentThread();//返回当前执行的线程对象
public String toString();
public void start();//启动线程对象
}
使用上述两种类都可以构造线程,二者的主要区别:
1.继承Thread类。声明一个线程类继承Thread类并覆盖run()方法,,这种方法的有点是该线程类的对象就是线程对象,且具有线程体。缺点就是不适合多继承。
2.实现Runnable接口。声明一个线程类实现Runnable接口,该类创建的对象不是线程对象,它作为一个线程对象的目标对使用,所以还需要同时声明一个Thread类对象。
线程对象的优先级
java提供了10哥等级的线程优先级,分别用1-10表示,默认值为5。Thread类声明了一下3个表示优先级的公有静态常量:
public static final int MIN_PRIORITY = 1 //最低优先级
public static final int MAX_PRIORITY = 10 //最高优先级
public static final int NROM_PRIORITY = 5 //默认优先级
可以通过以下方法获取和设置线程优先级:
public final int getPriority() //获得线程优先级
public final void setPriority(int priority) //设置线程优先级
线程对象的生命周期
在java中,线程对象有以下6种状态
线程状态说明:
1.新建态。new Tread()创建的线程对象处于新建态NEW,系统没有为它分配资源。
2.运行态。从操作系统的角度看,处于新建态的线程启动后,进入就绪态,再由操作系统调度执行成为运行态。
3.阻塞态和等待态。一个运行态的线程因某种原因不能继续运行,进入阻塞态或等待态。处于阻塞态或等待态的线程不能执行,即使处理器空闲也不能执行。只有阻塞的原因消除,或等待条件满足,线程才能转为运行态。
4.终止态。线程对象停止运行未被撤销时是终止态。线程运行结束或者强制停止都可以使得线程进入终止态。
java线程对象的状态及状态变化:
以下是我写的关于多线程处理银行账户的一个例子。
1package ThreadTest;
2
3public class Account {
4
5 public String name;
6 public double balance;
7
8 public Account(String name) {
9 super();
10 this.name = name;
11 this.balance = 0;
12 }
13
14 public void desposit(double value) {
15 this.balance += value;
16 }
17
18 public void withdraw(double value) {
19 this.balance -= value;
20 }
21
22 public static void main(String[] args) {
23 System.out.println("brooke");
24 Account brooke = new Account("brooke");
25 new DespositThread(brooke, 10000).start();
26 new DespositThread(brooke, 10000).start();
27 new WithdrawThread(brooke, 1000).start();
28 }
29}
30
31class DespositThread extends Thread{
32 private Account account;
33 private double value;
34
35 public DespositThread(Account account, double value) {
36 super();
37 this.account = account;
38 this.value = value;
39 }
40
41 @Override
42 public void run() {
43 synchronized(account) {
44 double Nowbalance = account.balance;
45 account.desposit(value);
46 try {
47 sleep(1);
48 } catch (InterruptedException e) {
49 }
50 System.out.println(account.name + "账户:现有"+Nowbalance+", 存入"
51 +value+",余额为"+account.balance);
52 }
53 }
54}
55
56class WithdrawThread extends Thread{
57
58 private Account account;
59 private double value;
60
61 public WithdrawThread(Account account, double value) {
62 super();
63 this.account = account;
64 this.value = value;
65 }
66
67 @Override
68 public void run() {
69 synchronized(account) {
70 double Nowbalance = account.balance;
71 account.withdraw(value);;
72 try {
73 sleep(1);
74 } catch (InterruptedException e) {
75 }
76 System.out.println(account.name + "账户:现有"+Nowbalance+", 取出"
77 +value+",余额为"+account.balance);
78 }
79 }
80}