多线程在Java中的用法有哪些
更新时间:2023-10-08Java多线程基础概念
Java多线程是Java语言的重要特性之一,允许程序同时执行多个线程。在Java中,每个线程都是继承自Thread类或实现Runnable接口的Java类。当我们创建一个线程并调用start()方法时,线程会在一个新的线程中执行代码。由于线程是并发执行的,所以我们需要考虑线程安全问题,以避免多个线程同时访问同一个共享资源。
public class SimpleThread extends Thread {
@Override
public void run() {
System.out.println("This is a simple thread");
}
}
public class Main {
public static void main(String[] args) {
SimpleThread thread = new SimpleThread();
thread.start();
}
}
上面这个例子展示了如何创建一个简单的线程并启动它。这个例子创建了一个类SimpleThread,继承了Thread类并重写了run()方法。在主函数中,我们需要创建SimpleThread的实例并启动它。调用start()方法后,线程会在一个新的线程中执行run()方法中的代码。
Java线程池的使用
在Java多线程中,线程池是一种常用的技术,它可以帮助我们更好地控制线程的数量和生命周期。线程池包含了一组线程,如果有任务需要执行,就可以从线程池中获取一个空闲线程来执行任务。线程池可以节省时间和开销,还可以避免过度创建线程导致程序崩溃。
public class ThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i=0; i<5; i++) {
Runnable worker = new WorkerThread(""+i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
Thread.sleep(1000);
}
System.out.println("Finished all threads");
}
}
class WorkerThread implements Runnable {
private String message;
public WorkerThread(String s){
this.message=s;
}
public void run() {
System.out.println(Thread.currentThread().getName()+" (Start) message = "+message);
processMessage();//call processMessage method that sleeps the thread for 2 seconds
System.out.println(Thread.currentThread().getName()+" (End)");//prints thread name
}
private void processMessage() {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
}
}
这个例子展示了如何创建一个线程池并提交任务。我们调用了Executors工厂类的newFixedThreadPool()方法来创建大小固定的线程池,线程池大小为2。接着,我们创建了5个工作线程并将它们提交到线程池中。最后,我们关闭了线程池并等待所有线程运行完成。
Java锁的使用
在Java多线程中,锁机制是用来解决线程同步问题的重要手段。Java语言提供了多种不同类型的锁,比如互斥锁、条件锁、读写锁等,分别适用于不同的场景。互斥锁是最常用的锁机制,可以保证同一时刻只有一个线程访问某个共享资源。
public class Counter {
private int count = 0;
private Object lock = new Object();
public void increment() {
synchronized(lock) {
count++;
}
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws Exception {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.getCount());
}
}
这个例子展示了如何使用互斥锁来保证线程安全。我们创建了一个Counter类,其中有一个count属性。在increment()方法中,我们使用synchronized代码块来获取lock对象的锁,这样就保证了在一个时刻只有一个线程能够访问count属性。为了测试这个类,我们创建了两个线程来共享Counter实例并调用increment()方法。最后,我们输出了count属性的值,确认它的值是正确的。
Java同步器的使用
在Java多线程中,同步器是一种高级技术,它可以更好地管理线程的同步和协作。Java提供了多种同步器,包括Semaphore、CountDownLatch、CyclicBarrier等,它们分别适用于不同的场景。Semaphore是一种允许多个线程同时访问某个共享资源的同步器,CountDownLatch是一种等待所有线程完成某个任务再进行下一步操作的同步器,CyclicBarrier是一种等待一组线程全部完成某个操作后再继续执行的同步器。
public class PrintTask implements Runnable {
private String message;
private CyclicBarrier barrier;
public PrintTask(String message, CyclicBarrier barrier) {
this.message = message;
this.barrier = barrier;
}
@Override
public void run() {
System.out.println(message);
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int threads = 5;
CyclicBarrier barrier = new CyclicBarrier(threads, () -> System.out.println("All threads finished!"));
for (int i = 0; i < threads; i++) {
new Thread(new PrintTask("Hello from thread " + i, barrier)).start();
}
}
}
这个例子展示了如何使用CyclicBarrier来等待一组线程全部完成某个操作后再进行下一步操作。我们创建了一个PrintTask类,其中包含了一个message属性和一个CyclicBarrier对象。在run()方法中,线程首先输出message属性,然后调用barrier.await()方法来等待其他线程。main()方法中,我们创建了5个PrintTask对象,并启动了5个线程来执行它们,同时传入了同一个CyclicBarrier对象。当所有线程都执行完毕后,CyclicBarrier会自动执行等待操作后面的代码,从而输出"All threads finished!"提示。