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

Java多线程函数的使用方法和实例

发布时间:2023-06-03 15:53:15

Java多线程是Java语言的核心特性之一,多线程编程可以帮助我们充分利用计算机多核心的优势,提高程序的执行效率。Java多线程提供了一些常用的函数,如Thread、Runnable、Lock、synchronized、wait、notify等,下面就来详细介绍一下这几个函数的使用方法和实例。

一、Thread

Thread是Java多线程中最基本的类,它表示一个独立的线程,可以调用start()方法来启动线程。Thread还有一些常用的方法,如sleep()、yield()、join()、interrupt()等。

1. sleep()

sleep()方法可以让当前线程暂停一段时间,让其他线程有机会执行。sleep()方法的参数是一个long类型的毫秒数,表示暂停的时间。

下面是一个使用sleep()方法的例子:

public class SleepDemo {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            System.out.println("打印第" + i + "行");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

上面的代码会打印5行文字,每行文字之间暂停1秒钟。

2. yield()

yield()方法可以让当前线程暂停一下,让其他具有相同优先级的线程有机会执行。但是,yield()方法并不能保证给其他线程执行的机会,因为依赖于操作系统的实现。

下面是一个使用yield()方法的例子:

public class YieldDemo {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            System.out.println("打印第" + i + "行");
            Thread.yield();
        }
    }
}

上面的代码会打印5行文字,每行文字之间暂停一小会儿,让其他线程有机会执行。

3. join()

join()方法可以让一个线程等待另一个线程完成后再继续执行。join()方法的原理是让当前线程进入等待状态,直到被等待的线程结束后,再唤醒它。

下面是一个使用join()方法的例子:

public class JoinDemo {
    static Thread t1 = new Thread(() -> {
        for (int i = 1; i <= 5; i++) {
            System.out.println("线程1,打印第" + i + "行");
        }
    });
    static Thread t2 = new Thread(() -> {
        for (int i = 1; i <= 5; i++) {
            System.out.println("线程2,打印第" + i + "行");
        }
    });

    public static void main(String[] args) throws InterruptedException {
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("所有线程执行完毕");
    }
}

上面的代码启动了两个线程,分别打印5行文字,然后让主线程等待这两个子线程执行完毕后再打印一行文字。

4. interrupt()

interrupt()方法可以中断一个线程,将其状态设为中断状态。但是,中断状态只是一个标记,线程执行的代码需要自己检查中断状态并处理。

下面是一个使用interrupt()方法的例子:

public class InterruptDemo {
    static Thread t = new Thread(() -> {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("线程执行中...");
        }
        System.out.println("线程被中断");
    });

    public static void main(String[] args) throws InterruptedException {
        t.start();
        Thread.sleep(1000);
        t.interrupt();
    }
}

上面的代码启动了一个线程,这个线程会不断打印一行文字,直到被中断为止。主线程调用了t.interrupt()方法,将子线程的中断状态标记为true,子线程在下一个循环中检查到中断状态,跳出循环。

二、Runnable

Runnable接口表示一个可运行的任务,可以被Thread类实例化并启动。通常情况下,我们把需要执行的操作封装在一个Runnable接口实现类中,然后把这个实现类的实例传递给Thread类的构造方法。

下面是一个使用Runnable接口的例子:

public class RunnableDemo implements Runnable {
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("打印第" + i + "行");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread t = new Thread(new RunnableDemo());
        t.start();
    }
}

上面的代码定义了一个Runnable接口实现类RunnableDemo,这个类实现了run()方法,在方法中打印5行文字,然后暂停一秒钟。在main()方法中,我们创建了一个Thread类的实例,并把RunnableDemo类的实例传递给它。最后调用t.start()方法启动线程。

三、Lock

Lock是Java多线程中提供的另一种互斥机制,可以替代synchronized关键字。Lock提供了比synchronized更细粒度的控制,支持自旋、公平锁和读写锁等特性。

下面是一个使用Lock的例子:

public class LockDemo {
    private static final Lock lock = new ReentrantLock();
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                lock.lock();
                try {
                    for (int j = 0; j < 10000; j++) {
                        count++;
                    }
                } finally {
                    lock.unlock();
                }
            });
            threads[i].start();
        }

        for (Thread thread : threads) {
            thread.join();
        }

        System.out.println(count);
    }
}

上面的代码定义了一个静态变量count和一个Lock对象lock,然后在main()方法中创建了一个长度为10的线程数组,每个线程执行循环10000次,对count变量进行++操作。在每个线程的执行过程中,我们使用lock.lock()和lock.unlock()方法来获得和释放锁。最后打印count变量的值。

四、synchronized

synchronized是Java多线程中最基础和常用的互斥机制,用于控制多个线程对同一个共享资源的访问。synchronized有两种使用方式,一种是对方法进行同步,另一种是对代码块进行同步。

下面是一个使用synchronized的例子:

public class SynchronizedDemo {
    private static int count = 0;

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

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    increment();
                }
            });
            threads[i].start();
        }

        for (Thread thread : threads) {
            thread.join();
        }

        System.out.println(count);
    }
}

上面的代码定义了一个静态变量count和一个静态的synchronized方法increment(),在方法中对count变量进行++操作。在main()方法中,我们创建了一个长度为10的线程数组,每个线程执行循环10000次,调用increment()方法对count变量进行操作。由于increment()方法加了synchronized关键字,因此对count变量的操作会被串行化,保证了线程安全。