JAVA-多线程编程

本文详细介绍了Java中多线程编程的概念、创建和启动线程的方式、线程同步和互斥、线程通信、线程调度、线程池、线程安全性和线程局部变量、线程安全的集合类、并发工具类、多线程性能调优以及并行计算和分布式计算等。通过示例代码展示了如何使用synchronized关键字、Lock接口、线程通信方法、线程池和并发工具类等,帮助理解多线程编程的关键点和实践技巧。
摘要由CSDN通过智能技术生成

多线程编程是指在一个程序中同时执行多个线程,每个线程都是独立运行的、拥有自己的执行路径和指令序列。在Java中,多线程编程可以使用java.lang.Thread类或者实现java.lang.Runnable接口来创建线程。

多线程编程可以提高程序的并发性和效率,特别适用于需要同时执行多个任务或者处理多个事件的场景。

目录

1. 线程创建和启动:

2. 线程同步和互斥:

3. 线程通信:

4. 线程调度:

5. 线程池:

6. 线程安全性和线程局部变量:

7. 线程安全的集合类:

8. 并发工具类:

9. 多线程的性能和调优:

10. 并行计算和分布式计算:

11. Java内存模型:

12. 并发编程的常见问题和解决方案:

总结:


1. 线程创建和启动:

使用Thread类的构造方法创建线程对象,然后调用start()方法来启动线程。线程启动后会自动执行run()方法中的代码。

1). 使用Thread类创建和启动线程:

   - 第一步,创建一个Thread子类,并重写其run()方法,该方法中包含线程需要执行的代码

   public class MyThread extends Thread {
       @Override
       public void run() {
           // 线程执行的代码
           System.out.println("Hello from MyThread!");
       }
   }

   - 第二步,实例化Thread的子类,并调用start()方法来启动线程。

  public class Main {
       public static void main(String[] args) {
           Thread myThread = new MyThread();
           myThread.start();
       }
   }

   在上述代码中,我们创建了一个名为`MyThread`的Thread子类,并重写了它的`run()`方法,在`run()`方法中打印了一条消息。然后在`Main`类的`main()`方法中,我们实例化了`MyThread`类,并调用`start()`方法来启动线程。

   线程的启动通过`start()`方法来实现,该方法会启动一个新的线程并调用该线程的`run()`方法。注意,不要直接调用`run()`方法,这样不会创建新的线程,而是在当前线程中执行`run()`方法。

2). 实现Runnable接口创建和启动线程:

   - 第一步,创建一个实现了Runnable接口的类,并实现其run()方法。

   public class MyRunnable implements Runnable {
       @Override
       public void run() {
           // 线程执行的代码
           System.out.println("Hello from MyRunnable!");
       }
   }

   - 第二步,实例化实现了Runnable接口的类,并将其传递给Thread类的构造方法中。

  public class Main {
       public static void main(String[] args) {
           Runnable myRunnable = new MyRunnable();
           Thread thread = new Thread(myRunnable);
           thread.start();
       }
   }

   在上述代码中,我们创建了一个名为`MyRunnable`的实现了Runnable接口的类,并实现了其`run()`方法,在`run()`方法中打印了一条消息。然后在`Main`类的`main()`方法中,我们实例化了`MyRunnable`类,并将其传递给`Thread`类的构造方法中,最后调用`start()`方法启动线程。

   通过实现Runnable接口来创建线程的好处是可以避免Java单继承的限制,可以继续继承其他类。此外,使用Runnable接口还可以使代码更具可读性和可维护性。

无论是使用Thread类还是实现Runnable接口,线程的创建和启动都是通过实例化线程对象并调用start()方法来实现的。启动线程后,线程会在自己的执行路径上执行run()方法中的代码。

2. 线程同步和互斥:

线程同步和互斥是多线程编程中重要的概念,用于确保多个线程对共享资源的安全访问。下面我将详细介绍线程同步和互斥的概念,并提供具体的代码解释。

线程同步是指协调多个线程之间的执行顺序,以保证它们对共享资源的访问是安全的。当多个线程同时访问共享资源时,可能会出现线程之间的数据竞争和冲突,导致程序运行出错或产生不确定的结果。为了避免这种情况,我们可以使用同步机制来保证线程的互斥访问,即同一时间只有一个线程可以访问共享资源。

在Java中,常用的线程同步机制包括使用synchronized关键字和Lock接口实现的锁机制。下面分别介绍这两种方式的线程同步:

1). 使用synchronized关键字:   - 对象级别的同步:使用synchronized关键字修饰方法或代码块,保证在同一时间只有一个线程能够访问被synchronized修饰的代码块或方法。

   public class MyThread {
       private int count;

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

   在上述示例中,我们使用synchronized关键字修饰了`increment()`方法,保证了对`count`变量的原子性操作。同一时间只有一个线程能够执行`increment()`方法。   - 对象内部锁:使用synchronized关键字修饰一个对象,实现对该对象的内部锁定。

 public class MyThread implements Runnable {
       private Object lock;

       public MyThread(Object lock) {
           this.lock = lock;
       }

       public void run() {
           synchronized (lock) {
               // 互斥代码块
           }
       }
   }

   在上述示例中,我们使用synchronized关键字将互斥代码块 `synchronized (lock)` 置于需要同步的位置。这里的`lock`对象可以是任意对象,它在多个线程之间充当同步锁。

2). 使用Lock接口实现的锁机制:   Lock接口提供了更为灵活的锁定机制,相比synchronized关键字,它提供了更多的功能和对细粒度的控制。

  import java.util.concurrent.locks.Lock;
   import java.util.concurrent.locks.ReentrantLock;

   public class MyThread {
       private int count;
       private Lock lock = new ReentrantLock();

       public void increment() {
           lock.lock();
           try {
               count++;
           } finally {
               lock.unlock();
           }
       }
   }

   在上述示例中,我们使用了Lock接口及其实现类ReentrantLock来实现线程同步。通过调用`lock()`方法获取锁,并在finally块中调用`unlock()`方法释放锁。

   使用Lock接口的好处是可以更加灵活地控制锁的获取和释放,例如使用try-finally语句块确保锁在异常情况下能够正确释放。

无论是使用synchronized关键字还是Lock接口,线程同步都能够确保在同一时间只有一个线程能够访问共享资源,从而避免数据竞争和冲突的发生。

3. 线程通信:

线程通信是指多个线程之间通过某种方式进行数据的交换和协调,以实现线程间的合作和同步。线程通信的目的通常是实现线程间的数据共享和协作,避免竞态条件和死锁。

在Java中,常用的线程通信方式有以下几种:

1). 共享变量:多个线程共享同一个变量,通过读写该变量来实现线程间的信息传递和同步。为了保证线程安全,可以使用关键字synchronized或使用锁机制(如ReentrantLock)来对共享变量进行保护。

示例代码:

class SharedData {
    private int data;
    private boolean isReady = false;

    public synchronized void writeData(int newData) {
        // 写入新数据
        data = newData;

        // 设置标志位为true,表示数据已准备好
        isReady = true;

        // 唤醒等待的读线程
        notify();
    }

    public synchronized int readData() throws InterruptedException {
        // 如果数据还没准备好,则等待
        while (!isReady) {
            wait();
        }

        // 读取数据
        int result = data;

        // 重置标志位,表示数据已被消费
        isReady = false;

        return result;
    }
}

class WriterThread extends Thread {
    private SharedData sharedData;

    public WriterThread(SharedData sharedData) {
        this.sharedData = sharedData;
    }

    public void run() {
        // 生成新数据
        int newData = 10;

        // 写入数据
        sharedData.writeData(newData);
    }
}

class ReaderThread extends Thread {
    private SharedData sharedData;

    public ReaderThread(SharedData sharedData) {
        this.sharedData = sharedData;
    }

    public void run() {
        try {
            // 读取数据
            int data = sharedData.readData();
            System.out.println("Read data: " + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        SharedData sharedData = new SharedData();

        WriterThread writerThread = new WriterThread(sharedData);
        ReaderThread readerThread = new ReaderThread(sharedData);

        writerThread.start();
        readerThread.start();
    }
}

在上述示例中,通过共享变量data和isReady实现线程间的信息传递。写线程通过调用共享对象的`writeData()`方法写入新数据,并唤醒等待的读线程;读线程通过`readData()`方法等待数据准备好后读取数据。

2). 管道(Piped)流:使用PipedInputStream和PipedOutputStream来实现线程间的单向通信。一个线程使用PipedOutputStream将数据写入管道,另一个线程使用PipedInputStream从管道中读取数据。

示例代码:

class WriterThread extends Thread {
    private PipedOutputStream pipedOutputStream;

    public WriterThread(PipedOutputStream pipedOutputStream) {
        this.pipedOutputStream = pipedOutputStream;
    }

    public void run() {
        try {
            // 写入数据
            pipedOutputStream.write(10);
            pipedOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ReaderThread extends Thread {
    private PipedInputStream pipedInputStream;

    public ReaderThread(PipedInputStream pipedInputStream) {
        this.pipedInputStream = pipedInputStream;
    }

    public void run() {
        try {
            // 读取数据
            int data = pipedInputStream.read();
            System.out.println("Read data: " + data);
            pipedInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        PipedInputStream pipedInputStream = new PipedInputStream();
        PipedOutputStream pipedOutputStream = new PipedOutputStream();

        try {
            // 连接输入流和输出流
            pipedInputStream.connect(pipedOutputStream);
        } catch (IOException e) {
            e.printStackTrace
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值