Java线程技术详解

1.什么是线程?

线程是程序执行的单元,它是操作系统中调度的最小单位。
线程在程序中可以比较好地完成并发执行。

2.创建线程的两种方式
(1)继承Thread类,重写run()方法
(2)实现Runnable接口

3.线程的状态图
(1)NEW:线程已经被创建但是还没有开始执行
(2)RUNNABLE:线程正在执行或者准备执行
(3)BLOCKED:线程被阻塞,等待获取的锁
(4)WAITING:当前线程处于等待状态,等待其他线程通知
(5)TIMED_WAITING:等待一定的时间后继续执行
(6)TERMINATED:线程执行结束,结束状态

4.线程的创建方法
(1)继承Thread类,重写run()方法
```
public class MyThread extends Thread {
public void run() {
System.out.println("MyThread is running.");
}
}
```

(2)实现Runnable接口
```
public class MyRunnable implements Runnable {
public void run() {
System.out.println("MyRunnable is running.");
}
}
```
5.线程的启动
Thread类中的start()方法用于启动线程,Thread对象只能调用一次start()方法。

```
MyThread myThread = new MyThread();
myThread.start();
Thread thread = new Thread(new MyRunnable());
thread.start();
```

6.线程的中断
Thread类中提供了中断线程的方法,即interrupt()方法。
当线程A调用了线程B的interrupt()方法时,线程B会收到一个中断信号并抛出一个InterruptedException异常,从而退出原本的执行过程。

```
public class MyThread extends Thread {
public void run() {
while (true) {
try {
// sleep可以带一个时间参数,也可以不带
Thread.sleep(1000);
System.out.println("MyThread is running.");
} catch (InterruptedException e) {
// 线程被中断时会执行到这里
System.out.println("Thread is interrupted");
// 此时可以只打印出日志就返回,也可以做一些清理工作
return;
}
}
}
}
```

7.线程的同步
当多个线程访问共享资源时,可能会产生冲突,为了避免冲突,需要对访问共享资源的线程进行同步。
Java提供了synchronized关键字和Lock对象实现线程同步。

(1)synchronized
synchronized关键字可以用来修饰方法或代码块。
修饰方法时,锁的是当前对象(即this)
修饰代码块时,需要指定同步锁对象。

```
public class MyThread extends Thread {
public synchronized void print() {
...
}

public void run() {
print();
...
}
}
```

(2)Lock对象
Lock对象和synchronized一样可以保证线程同步的效果,并且相比于synchronized更加灵活和高效。
注意:Lock对象要手动释放锁,它不能像synchronized一样在方法结束时自动释放锁。

```
public class MyThread extends Thread {
private Lock lock = new ReentrantLock();

public void print() {
lock.lock(); //获取锁
try {
...
} finally {
lock.unlock(); //释放锁
}
}

public void run() {
print();
...
}
}
```

8.线程的通信
线程的通信指的是多个线程之间的数据传输或控制传递。常用的方法有wait/notify,await/signal等。

(1)wait/notify
wait()方法用于将当前线程进入等待状态并释放锁,直到其他线程调用notify()方法才能继续执行。
notify()方法用于唤醒等待中的线程。

```
public class ThreadA {
public void print() {
synchronized (this) {
System.out.println("ThreadA start.");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadA end.");
}
}
}

public class ThreadB {
public void print() {
synchronized (this) {
System.out.println("ThreadB start.");
notify();
System.out.println("ThreadB end.");
}
}
}

public class Test {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB();

new Thread(() -> {
threadA.print();
}).start();

new Thread(() -> {
threadB.print();
}).start();
}
}
```

(2)await/signal
await()方法用于将当前线程进入等待状态,直到其他线程调用signal()方法才能继续执行。
signal()方法用于唤醒等待中的线程。

```
public class ThreadA {
public void print() {
lock.lock();
try {
System.out.println("ThreadA start.");
condition.await();
System.out.println("ThreadA end.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

public class ThreadB {
public void print() {
lock.lock();
try {
System.out.println("ThreadB start.");
condition.signal();
System.out.println("ThreadB end.");
} finally {
lock.unlock();
}
}
}

public class Test {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB();

new Thread(() -> {
threadA.print();
}).start();

new Thread(() -> {
threadB.print();
}).start();
}
}
```

9.线程的性能调优
(1)使用线程池
线程池中维护了一组线程,避免了创建和销毁线程的开销。

```
public class Test {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
// 执行任务
});
}
executorService.shutdown();
}
}
```

(2)避免死锁
死锁是指两个

东卫11:02或多个进程或线程,因竞争资源而造成的一种僵局状态,若无外力作用,它们都将无法继续向前推进,这时称系统处于死锁状态。死锁的发生是由于两个或多个执行单元(一般是进程或线程)互相请求对方占有的资源,导致这些进程或线程都陷入无限期的等待状态,等待对方放弃已经占用的资源。出现死锁后,系统始终都处于饱和状态,不能为正常进行的进程提供必要的资源,从而导致了进程无限期地阻塞,不能正常提示。

因此在编写程序时,我们需要注意以下几点:
- 永远只占用一个锁。
- 如果需要占用两个或多个锁,请确保在同一顺序下请求锁。
- 尽量使用同步代码块代替同步方法。
- 避免死锁:尽量减少同步块中的代码量,分离任务(当过多线程在等待同一个锁时,便容易造成死锁)。

(3)减少上下文切换
在并发编程中,线程的上下文切换会带来性能的损失,因此我们需要尽量减少上下文切换的次数。减少上下文切换可以有以下几种方法:
- 减少线程的数量
- 使用同步块而不是同步方法
- 使用CAS(Compare-and-Swap,比较并交换)算法
- 使用无锁编程技术

(4)减少线程的阻塞时间
在并发编程中,线程的阻塞会带来时间的浪费,因此我们需要尽量减少线程的阻塞时间。减少线程的阻塞时间可以有以下几种方法:
- 使用非阻塞的算法替代阻塞算法
- 使用异步方式替代同步方式
- 做好资源的管理和调度工作

10.趣味小知识
- 在Java中,线程是一种非常常见的概念,因此Java的类库提供了很多关于线程的API。
- Java虚拟机中有两个线程:主线程和垃圾收集线程。
- 多线程的并发性和多个CPU之间的并行性有区别,前者利用同一个CPU上的多个线程并发执行;而后者则利用多个CPU上的多个线程并行执行,可以有效地提高程序的执行速度。
- Java平台支持的并发包括:synchronized,Executor框架,Concurrent套件以及原子变量。特别是Concurrent套件提供了对代码块、集合类、执行器等的支持,可以用于解决大量并发问题。
- Java中的线程状态是由操作系统控制的,Java只是将其进行了抽象,封装成了线程模型。操作系统控制线程的方式有多种,可以采用抢占式、协作式等方式,而Java虚拟机中采用协作式的线程调度方式。

综上所述,Java线程技术的学习和应用非常重要,可以提高程序的性能和效率,同时也能够充分利用多核CPU的优势,实现并发执行。需要大家不断深入理解线程概念、同步机制、线程池以及线程通信等知识点,并将其应用到实际项目中,才能真正实现Java线程技术的优化和提升。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NasaYIN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值