JAVA多线程知识汇总
为什么需要多线程
在单线程模式下,当代码执行到IO操作时,CPU资源就会空闲等待IO操作完成,这样会导致CPU效率低下。而多线程模式下,线程的数量可以与CPU的核心数相匹配,能够更好地充分利用CPU资源,在IO操作等待的同时处理其他代码而不会浪费CPU。
如何使用多线程
创建线程
Java中使用继承Thread类或者实现Runnable接口的方式来创建线程,其中Runnable接口比Thread类更为推荐,因为其能够避免单继承的局限性,也允许更好地扩展和修改线程行为。
以下代码示例为实现Runnable接口的方式创建线程:
public class MyThread implements Runnable {
public void run() {
System.out.println("Starting MyThread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Ending MyThread");
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
System.out.println("main() is ending...");
}
}
线程同步
当多个线程同时访问共享资源时,会发生线程安全问题。为了解决这个问题,Java提供了锁机制来保证线程安全。其中最基本的锁机制是synchronized关键字。
以下代码示例为加锁操作的示例:
public class SynchronizedDemo implements Runnable {
private static int count;
public static void main(String[] args) {
SynchronizedDemo synchronizedDemo = new SynchronizedDemo();
Thread thread1 = new Thread(synchronizedDemo);
Thread thread2 = new Thread(synchronizedDemo);
thread1.start();
thread2.start();
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
addCount(); // 对count的访问是同步的
System.out.println(Thread.currentThread().getName() + " count value: " + count);
}
}
private synchronized void addCount() {
count++;
}
}
线程通信
Java中提供了wait()、notify()、notifyAll()等方法来实现线程之间的通信。其中wait()方法可以使线程等待,notify()、notifyAll()方法可以唤醒等待的线程。
以下代码示例为线程通信的示例:
public class WaitNotifyDemo {
public static void main(String[] args) throws InterruptedException {
TaskQueue taskQueue = new TaskQueue();
Thread producerThread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
String task = "Task " + i;
System.out.println("Producing " + task);
taskQueue.addTask(task);
}
});
Thread consumerThread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
String task = null;
try {
task = taskQueue.getTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consuming " + task);
}
});
producerThread.start();
consumerThread.start();
producerThread.join();
consumerThread.join();
}
}
class TaskQueue {
private Queue<String> queue = new LinkedList<>();
public synchronized void addTask(String task) {
queue.add(task);
notifyAll(); // 通知所有等待线程
}
public synchronized String getTask() throws InterruptedException {
while (queue.isEmpty()) {
wait(); // 等待,释放锁
}
return queue.remove();
}
}
多线程常见问题
死锁
死锁是指多个线程因等待对方所持有的资源而发生的死循环,导致所有线程都无法继续执行。一般来说,死锁的原因是两个或多个线程试图获取彼此持有的锁,并且都不释放自己持有的锁。为了避免死锁,应该尽量避免持有多个锁,并按照固定顺序申请锁。
线程安全
在多线程中访问同一共享变量时,如果不加锁访问这个变量,就会存在线程不安全问题。线程安全是指多个线程访问同一资源时,不会发生不可预期的结果。为了保证线程安全,可以使用synchronized关键字或者使用Lock机制来对共享变量进行加锁。
需要注意的问题
在多线程编程时,需要避免一些常见的问题:
- 避免使用共享变量的时候不加锁的情况。
- 避免使用Thread.stop()方法来停止线程,因为该方法会导致线程中断状态的突然改变,容易产生线程安全问题。
- 避免使用Thread.suspend() 和 Thread.resume()方法,因为这两个方法容易导致线程死锁和卡死等问题。
总结
多线程是Java编程中非常重要的一个方面,可以更好地利用CPU资源以及提高程序性能。但是多线程也存在一些问题,需要程序员注意。
以上就是JAVA多线程知识的完整攻略,有了这些知识,相信你已经能够熟练地使用Java多线程了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JAVA多线程知识汇总 - Python技术站