Java中的多线程函数:从创建线程到线程同步和互斥。
Java是一种支持多线程编程的语言,多线程使程序能够同时执行多个任务,提高了程序的实时性和效率。在Java中,线程是通过创建Thread类的对象来实现的。本文将介绍Java中的多线程函数,从创建线程到线程同步和互斥,详细阐述Java中多线程的实现和使用方法。
一、创建线程
Java中创建线程有两种方式:继承Thread类和实现Runnable接口。继承Thread类需要重写run()方法,实现Runnable接口需要实现run()方法。以下是两种创建线程的示例代码:
1.继承Thread类
class MyThread extends Thread {
public void run() {
System.out.println("线程执行了");
}
}
MyThread t = new MyThread();
t.start();
2.实现Runnable接口
class MyRunnable implements Runnable {
public void run() {
System.out.println("线程执行了");
}
}
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
以上两种方法都可以创建线程,但是实现Runnable接口更加灵活,因为一个类只能继承一个类,但是可以实现多个接口。
二、线程状态
在Java中,线程有不同的状态,包括新建状态、就绪状态、运行状态、阻塞状态和死亡状态。
1.新建状态
当使用new关键字创建一个Thread对象时,线程处于新建状态。
Thread t = new Thread();
2.就绪状态
当调用start()方法后,线程处于就绪状态,等待CPU的调度。
t.start();
3.运行状态
当线程得到CPU时间片并执行run()方法时,线程处于运行状态。
4.阻塞状态
当线程等待某个条件的发生时,线程处于阻塞状态。阻塞状态分为三种:等待(wait)、睡眠(sleep)和阻塞(block)。
等待:
调用wait()方法会让当前线程进入等待状态,直到被唤醒。
synchronized (obj) {
while (<condition does not hold>)
obj.wait(); //必须在同步代码块内调用
// Perform action appropriate to condition
}
睡眠:
调用sleep()方法会让当前线程进入睡眠状态,不会释放锁,但是可以被interrupt方法打断。
try {
Thread.sleep(1000); //单位是毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
阻塞:
当调用阻塞方法时,直到获得锁之前线程将处于阻塞状态。
synchronized (obj) {
// Access or modify the shared variables "c1" and "c2"
...
}
5.死亡状态
当run()方法执行完毕或调用stop()方法时,线程处于死亡状态。
三、线程同步
Java中的多线程可能会出现竞态条件(race condition),多个线程在访问共享变量时可能会导致数据不一致。线程同步可以解决这个问题,让并发访问变得安全。
1.synchronized关键字
synchronized关键字可以保证线程访问共享变量的互斥性和可见性。对于一个方法或一个代码块,只有一个线程可以执行,其他线程必须等待。以下是synchronized关键字的示例代码:
1)在方法上加上synchronized关键字
public synchronized void add() {
count++;
}
2)在代码块中使用synchronized关键字
synchronized (this) {
count++;
}
2.volatile关键字
volatile关键字可以保证共享变量的可见性,但是不能保证操作的原子性。当一个线程修改了volatile变量,其他线程可以立即看到修改后的值。
private volatile int count = 0;
3.原子类
Java中提供了一些原子类,如AtomicInteger、AtomicLong、AtomicBoolean等,它们提供了一些原子操作方法,可以实现线程安全。以下是AtomicInteger的示例代码:
private AtomicInteger count = new AtomicInteger(0);
public void add() {
count.getAndIncrement();
}
四、线程互斥
Java中的互斥机制保证每个线程都可以获得需要的资源。Java中的互斥机制有synchronized、Lock、Semaphore等。
1.Lock
Lock是Java中的一个接口,可以使用它的实现类ReentrantLock来实现锁机制。以下是ReentrantLock的示例代码:
private ReentrantLock lock = new ReentrantLock();
public void add() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
2.Semaphore
Semaphore是一种计数器,用于控制同时访问某个资源的线程数。以下是Semaphore的示例代码:
private Semaphore semaphore = new Semaphore(1);
public void add() throws InterruptedException {
semaphore.acquire();
try {
count++;
} finally {
semaphore.release();
}
}
五、线程通信
Java中提供了wait()和notify()/notifyAll()方法来实现线程间的等待和通知。
1.wait()
wait()方法可以使当前线程暂停执行,直到被唤醒或者等待时间结束。以下是wait()方法的示例代码:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
// Perform action appropriate to condition
}
2.notify()
notify()方法唤醒一个等待中的线程,若多个线程等待,则随机选择一个唤醒。notifyAll()方法唤醒所有等待中的线程。以下是notify()方法的示例代码:
synchronized (obj) {
obj.notify();
}
六、总结
本文介绍了Java中的多线程函数,涵盖了线程的创建、状态、同步、互斥和通信等方面。多线程编程对于提高程序的效率和实时性非常重要,但是同时也带来了一定的难度和挑战。因此,在使用多线程技术时需要注意保证线程安全和避免出现死锁等问题。
