欢迎访问宙启技术站
智能推送

Java中的多线程函数:从创建线程到线程同步和互斥。

发布时间:2023-06-11 17:21:19

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中的多线程函数,涵盖了线程的创建、状态、同步、互斥和通信等方面。多线程编程对于提高程序的效率和实时性非常重要,但是同时也带来了一定的难度和挑战。因此,在使用多线程技术时需要注意保证线程安全和避免出现死锁等问题。