这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战
Java 多线程编程
Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
什么是Java多线程?
1、进程与线程
▶进程
- 当一个程序被运行,就开启了一个进程, 比如启动了qq,word
- 程序由指令和数据组成,指令要运行,数据要加载,指令被cpu加载运行,数据被加载到内存,指令运行时可由cpu调度硬盘、网络等设备
▶线程
- 一个进程内可分为多个线程
- 一个线程就是一个指令流,cpu调度的最小单位,由cpu一条一条执行指令
并行与并发
▶并发:单核cpu运行多线程时,时间片进行很快的切换。线程轮流执行cpu
▶并行:多核cpu运行 多线程时,真正的在同一时刻运行
创建多线程
继承 Thread 类
public class test0 {
public static void main(String[] args) {
Thread MyThread = new MyThread();
MyThread.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("hello myThread" + Thread.currentThread().getName());
}
}
复制代码
实现 Runnable
public class test0 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println("hello myRunnable" + Thread.currentThread().getName());
}
}
复制代码
暂停
Java中线程的暂停是调用java.lang.Thread
类的sleep
方法(注意是类方法)。该方法会使当前正在执行的线程暂停指定的时间,如果线程持有锁,sleep
方法结束前并不会释放该锁。
Java示例:
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.print(i + " ");
try {
Thread.sleep(1000); //当前main线程暂停1000ms
} catch (InterruptedException e) {
}
}
}
}
复制代码
上述代码中,当main线程调用Thread.sleep(1000)
后,线程会被暂停,如果被interrupt
,则会抛出InterruptedException
异常。
互斥
Java中线程的共享互斥操作,会使用synchronized关键字。线程共享互斥的架构称为监视(monitor),而获取锁有时也称为“持有(own)监视”。
每个锁在同一时刻,只能由一个线程持有。
注意:synchronized
方法或声明执行期间,如程序遇到任何异常或return,线程都会释放锁。
1、synchronized方法
//synchronized实例方法
public synchronized void deposit(int m) {
System.out.print("This is synchronized method.");
}
复制代码
注:synchronized实例方法采用this锁(即当前对象)去做线程的共享互斥。
//synchronized类方法
public static synchronized void deposit(int m) {
System.out.print("This is synchronized static method.");
}
复制代码
注:synchronized类方法采用类对象锁(即当前类的类对象)去做线程的共享互斥。如上述示例中,采用类.class(继承自java.lang.Class)作为锁。
2、synchronized声明
public void deposit(int m) {
synchronized (this) {
System.out.print("This is synchronized statement with this lock.");
}
synchronized (Something.class) {
System.out.print("This is synchronized statement with class lock.");
}
}
复制代码
注:synchronized声明可以采用任意锁,上述示例中,分别采用了对象锁(this)和类锁(something.class)
3、等待(wait)和通知(notify)
Object有两个很重要的接口:Object.wait()和Object.notify()
当在一个对象实例上调用了wait()方法后,当前线程就会在这个对象上等待。直到其他线程调用了这个对象的notify()方法或者notifyAll()方法。notifyAll()方法与notify()方法的区别是它会唤醒所有正在等待这个对象的线程,而notify()方法只会随机唤醒一个等待该对象的线程。
wait()、notify()和notifyAll()都需要在synchronized语句中使用
4、中断
java.lang.Thread类有一个interrupt
方法,该方法直接对线程调用。当被interrupt的线程正在sleep或wait时,会抛出InterruptedException
异常。
事实上,interrupt
方法只是改变目标线程的中断状态(interrupt status),而那些会抛出InterruptedException
异常的方法,如wait、sleep、join等,都是在方法内部不断地检查中断状态的值。
- interrupt方法
Thread实例方法:必须由其它线程获取被调用线程的实例后,进行调用。实际上,只是改变了被调用线程的内部中断状态;
- Thread.interrupted方法
Thread类方法:必须在当前执行线程内调用,该方法返回当前线程的内部中断状态,然后清除中断状态(置为false) ;
- isInterrupted方法
Thread实例方法:用来检查指定线程的中断状态。当线程为中断状态时,会返回true;否则返回false。
近期评论