c语言编程笔录

首页 >   > 笔记大全

笔记大全

Java项目中实现多线程并发编程的条件有哪些

更新时间:2023-11-13

1. 数据共享问题:

在Java中实现多线程编程的条件之一是数据共享。多个线程可能会同时访问共享的数据,因此需要保证数据在并发情况下的正确性。使用synchronized关键字可以保证在同一时刻只有一个线程可以访问该代码块。下面的示例展示了如何使用synchronized关键字来保证线程安全:

public class SharedData {
  private int count = 0;

  public synchronized void increment() {
    count++;
  }

  public synchronized void decrement() {
    count--;
  }

  public int getCount() {
    return count;
  }
}

public class MyThread implements Runnable {
  private SharedData data;

  public MyThread(SharedData data) {
    this.data = data;
  }

  public void run() {
    data.increment();
    data.decrement();
  }
}

2. 等待/通知机制:

另一个实现多线程编程的条件是等待/通知机制。在Java中,可以通过wait()和notify()/notifyAll()方法来实现等待/通知机制。wait()方法可以使线程进入等待状态,直到其他线程调用notify()或notifyAll()方法来通知它恢复执行。下面的示例演示了如何使用wait()和notify()/notifyAll()方法来实现等待/通知机制:

public class WaitNotifyExample {
  public static void main(String[] args) {
    Message message = new Message("Process it");
    Waiter waiter1 = new Waiter(message);
    new Thread(waiter1,"waiter1").start();
      
    Waiter waiter2 = new Waiter(message);
    new Thread(waiter2, "waiter2").start();
      
    Notifier notifier = new Notifier(message);
    new Thread(notifier, "notifier").start();
    System.out.println("All threads are started");
  }
}

class Message {
  private String msg;

  public Message(String str){
    this.msg=str;
  }

  public String getMsg() {
    return msg;
  }

  public void setMsg(String str) {
    this.msg=str;
  }
}

class Waiter implements Runnable{
  private Message msg;

  public Waiter(Message m){
    this.msg=m;
  }

  public void run(){
    String name = Thread.currentThread().getName();
    synchronized (msg) {
      try{
        System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
        msg.wait();
      }catch(InterruptedException e){
        e.printStackTrace();
      }
      System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
      //process the message now
      System.out.println(name+" processed: "+msg.getMsg());
    }
  }
}

class Notifier implements Runnable {
  private Message msg;

  public Notifier(Message msg) {
    this.msg = msg;
  }

  public void run() {
    System.out.println("Notifier thread started");
    try {
      Thread.sleep(1000);
      synchronized (msg) {
        msg.setMsg("Notifier work done");
        //msg.notify();
        msg.notifyAll();
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

3. 线程池:

另一个实现多线程编程的条件是线程池。在Java中,可以使用线程池来避免频繁地创建和销毁线程,从而提高性能和效率。线程池可以通过ThreadPoolExecutor类来创建,可以设置最大线程数、核心线程数、线程空闲时间等参数。下面的示例展示了如何使用线程池来执行多个任务:

public class ThreadPoolExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(5); //创建一个线程池,容纳5个任务

    for (int i = 0; i < 10; i++) {
      Runnable worker = new WorkerThread("" + i);
      executor.execute(worker); // 提交任务给线程池执行
    }
    executor.shutdown(); // 关闭线程池
    while (!executor.isTerminated()) { } // 等待所有任务完成
    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(); // 处理任务
    System.out.println(Thread.currentThread().getName() + " (End)");
  }

  private void processMessage() {
    try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
  }
}

4. 并发容器:

最后一个实现多线程编程的条件是并发容器。在Java中,可以使用并发容器来实现线程安全的数据存储和访问。并发容器包括ConcurrentHashMap、ConcurrentLinkedQueue、CopyOnWriteArrayList等。这些容器在内部实现中使用了锁和原子变量来确保线程安全。下面的示例展示了如何使用ConcurrentHashMap来实现线程安全的数据存储和访问:

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
  public static void main(String[] args) {
    ConcurrentHashMap map = new ConcurrentHashMap();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 3);
    map.put("D", 4);

    // 遍历并发哈希表的键值对
    for (String key : map.keySet()) {
      System.out.printf("%s: %d\n", key, map.get(key));
    }

    // 替换哈希表中的元素
    map.replaceAll((k, v) -> v+1);

    // 遍历并发哈希表的值
    for (int value : map.values()) {
      System.out.println(value);
    }
  }
}