一、什么是线程?
1、进程的概念
- 进程是指可执行程序并存放在计算机存储器的一个指令序列,它是一个动态执行的过程。
- 有的软件只有一个进程,如记事本;有的软件是由多个进程组成的。
早期的进程是单任务的,只能运行一个程序,现在的操作系统是多任务的操作系统,多个程序可以同时运行。
2、什么是线程?
线程是比进程还要小的运行单位,一个进程包含多个线程。
- 比如一个程序是由很多行代码组成的,这些代码就可以分成很多块,放到线程中,分别执行。
- 线程相当于一个子程序
时间片的轮转:把CPU的执行时间分成很多的小块,每一小块的时间都是固定的,我们将这一小块的时间成为时间片;时间片的时间可以非常短,比如1ms,多个软件同时运行,多个软件分别获取时间片去处理,对于CPU来讲,这些软件都是轮流运行的,但是由于分别运行的时间间隔非常短,对于我们使用者而言是察觉不到的,可以认为这些软件是同时运行的。
二、线程的创建
1、创建线程的几种方式
- 创建一个Thread类,或者一个Thread子类的对象。
-
2、Thread类
Thread类是一个线程类,位于java.lang包下 | 构造方法 | 说明 | | —- | —- | | Thread() | 创建一个线程对象 | | Thread(String name) | 创建一个具有指定名称的线程对象 | | Thread(Runnable target) | 创建一个基于Runnable接口实现类的线程对象 | | Thread(Runnable target,String name) | 创建一个基于Runnable接口实现类,并且具有指定名称的线程对象 |
Thread类的常用方法 | 方法 | 说明 | | —- | —- | | public void run() | 线程相关的代码写在该方法中(线程体的代码),一般需要重写 | | public void start() | 启动线程的方法 | | public static void sleep(long m) | 线程休眠m毫秒的方法 | | public void join() | 优先执行调用join()方法的线程,抢占资源 |
通过继承Thread类创建线程 ```java class MyThread extends Thread { public MyThread(String name) {
super(name);
} @Override public void run() {
for (int i = 0; i < 10; i++) {System.out.println(getName()+"正在运行"+i);}
} }
public class ThreadTest { public static void main(String[] args) { MyThread mt1 = new MyThread(“线程1”); MyThread mt2 = new MyThread(“线程2”); mt1.start(); mt2.start();
}
}
<a name="DJpsv"></a>#### 3、Runnable接口- 只有一个方法`run()`- Runnable是Java中用以实现线程的接口- 任何实现线程功能的类都必须实现该接口,Thread类实际上是实现了Runnable接口的。- 通过实现Runnable接口的方式创建,(为什么要实现Runnable接口?1、Java不支持多线程;2、不打算重写Thread类的其他方法)```javaclass PrintRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName()+"正在运行"+i);}}}public class RunnableTest {public static void main(String[] args) {PrintRunnable printRunnable = new PrintRunnable();Thread thread1 = new Thread(printRunnable,"线程1");Thread thread3 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "正在运行" + i);}}, "线程3");Thread thread2 = new Thread(printRunnable,"线程2");thread1.start();thread2.start();thread3.start();}}
三、线程的状态和生命周期
1、线程的状态
- 新建(new) :当创建一个Thread类或Thread子类对象的时候
- 可运行(Runnable):当已经创建好的线程对象去调用
start()f方法,这时候就进入了可运行状态,线程什么时候运行是由CPU来决定的,只有当线程获取到CPU的使用权的时候,它才能执行,所以线程调用start()方法之后,只是进入一个可运行状态,也把这种状态叫做就绪状态。 - 正在运行(Running):处于可运行状态的线程,一旦获取了CPU的使用权,就可以立即进入正在运行状态。
- 阻塞(Blocked):当线程受到了一些干扰的时候,就会进入阻塞状态,也就是它不在执行。
-
2、线程的声明周期,即线程从创建到启动,直至运行结束这段时间。也就是以上五个状态之间的相互转换过程。
3、sleep方法的使用
Thread类中的方法
public static void sleep(long millis)。- 休眠时间到了之后并不能让线程进入运行状态,只能进入一个可运行状态,可运行状态的线程只有获取带CPU的使用权之后,才能进入运行状态。
- 作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行、阻塞)。
- 参数为休眠的时间,单位是毫秒。
作用:可以用作计时器(有误差)、定期发送数据等。
class MyThread implements Runnable {@Overridepublic void run() {for (int i = 0; i < 15; i++) {System.out.println(Thread.currentThread().getName() + "正在运行" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}public class SleepTest {public static void main(String[] args) {MyThread myThread = new MyThread();Thread thread1 = new Thread(myThread, "线程1");thread1.start();Thread thread2 = new Thread(myThread, "线程2");thread2.start();}}
4、Join方法应用
Thread类的方法:
public final void join()/public final void join(long millis)- 作用:等待调用该方法的线程结束后才能执行/等待该线程终止的最长时间为millis毫秒
```java
class MyThread implements Runnable {
@Override
public void run() {
} }for (int i = 0; i < 500; i++) {System.out.println(Thread.currentThread().getName() + "正在执行" + i);}
public class JoinDemo { public static void main(String[] args) { Thread thread = new Thread(new MyThread(), “我的线程1”); thread.start(); try { thread.join(2); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 30; i++) { System.out.println(“主线程运行第” + i + “次”); } } }
<a name="w5hRI"></a>## 四、线程的调度<a name="eRTI3"></a>#### 1、线程优先级- Java为线程优先级提供了10个优先级- 优先级可以用整数1-10表示,数字越大,表示有限级别越高;超过范围会抛出异常- 主线程默认优先级为5- 还可以用优先级常量表示- MAX_PRIORITY:线程的最高优先级10- MIN_PRIORITY:线程的最低优先级1- NORM_PRIORITY:线程的默认优先级5- 优先级相关的方法| 方法 | 说明 || --- | --- || publc int getPriority() | 获取线程优先级的方法 || public void setPriority(int newPriority) | 设置线程优先级的方法 |```javaclass MyThread extends Thread {private String name;public MyThread(String name) {this.name = name;}@Overridepublic void run() {for (int i = 0; i < 50; i++) {System.out.println("线程" + name + "正在运行" + i);}}}public class PriorityDemo {public static void main(String[] args) {Thread thread1 = new Thread(new MyThread("1"));Thread thread2 = new Thread(new MyThread("2"));thread1.setPriority(10);thread2.setPriority(1);System.out.println("thread1 = " + thread1.getPriority());System.out.println("thread2 = " + thread2.getPriority());thread1.start();thread2.start();/* //获取主线程的优先级int priority = Thread.currentThread().getPriority();System.out.println("主线程的优先级:priority = " + priority);*//* for (int i = 0; i < 15; i++) {System.out.println("主线程正在运行"+i);}*/}}
2、多线程运行问题
- 各个线程 是通过竞争CPU时间而获得运行机会的
- 各线程什么时候得到CPU时间,占用多久,是不可预测的。
- 为了保证在存款和取款的时候,不宜徐其他线程对账户余额进行操作;需要将Bank对象进行锁定,使用synchronized实现,可以实现共享对象在同一个时刻只能被一个线程所访问。
synchronized关键字用在
问题:账户余额不够了怎么办?等待存入足够的钱后处理?
wait()方法:中断线程的执行,使线程等待(阻塞状态)notify()方法:唤醒等待的某一个线程,使其结束等待notifyAll():唤醒所有处于等待状态的线程,使它们结束等待
