c语言编程笔录

首页 >   > 笔记大全

笔记大全

多线程在Java中的用法有哪些

更新时间:2023-10-08

Java多线程基础概念

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!"提示。