【东软实训Day1】多线程

什么是多线程


1. 进程与线程

在谈及多线程之前先简单提及一下进程与线程。

进程: 进程是程序的一次执行过程。
线程: 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,一个线程只能属于一个进程。

2. 单线程与多线程

单线程: 单线程即一个进程有且仅有一个线程。在程序执行时,所走的程序路径会按照连续顺序排下来,前面的线程必须处理好,后面的才会执行。

例如在学生食堂中,每一个阿姨一天要卖300份饭,使用单线程就可以做到随时知道还有几份饭没有卖完,而且安全性较高,不用担心学生没给钱,但是缺点是速度慢,需要学生一个个排队。

单线程卖饭的示例代码如下:

public class SingleThreadTest {
    private static final int TOTAL_FOOD = 300;

    public static void main(String[] args) {
        Auntie auntie = new Auntie();
        int soldFood = 0;
        while (soldFood < TOTAL_FOOD) {
            soldFood++;
            auntie.sellFood(soldFood);
        }
        System.out.println("单线程卖饭完成。");
    }

    private static class Auntie {
        public void sellFood(Integer soldFood) {
            System.out.println(Thread.currentThread().getName() + " 卖出了第" + soldFood + "份饭。");
        }
    }
}

多线程: 多线程就是一个进程有多个线程。在程序执行时,所有线程会交替执行。后面的线程不用等待前面的线程处理完毕即可执行。

同样是卖300份饭,使用多线程就可以让多个阿姨一块去卖饭,速度快,等待时间大大缩短,但是缺点是安全性低,无法准确得知还剩下多少份饭,可能上一秒还有200份饭,下一秒就只有八九十份了。高铁抢票也是一样的原理,大学生应该深有感触。

多线程卖饭的示例代码如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreadTest {
    private static final int TOTAL_FOOD = 300;
    private static final int NUM_AUNTIES = 5;

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(NUM_AUNTIES);
        Auntie[] aunties = new Auntie[NUM_AUNTIES];
        for (int i = 0; i < NUM_AUNTIES; i++) {
            aunties[i] = new Auntie();
            executorService.execute(aunties[i]);
        }
        executorService.shutdown();
        while (!executorService.isTerminated()) {
            // 等待所有阿姨卖饭完成
        }
        System.out.println("多线程卖饭完成。");
    }

    private static class Auntie implements Runnable {
        private static final Object lock = new Object();
        private static int soldFood = 0;

        @Override
        public void run() {
            while (soldFood < TOTAL_FOOD) {
                synchronized (lock) {
                    if (soldFood < TOTAL_FOOD) {
                        soldFood++;
                        sellFood(soldFood);
                    }
                }
            }
        }

        public void sellFood(Integer soldFood) {
            System.out.println(Thread.currentThread().getName() + " 卖出了第" + soldFood + "份饭。");
        }
    }
}

3. 在java中使用多线程

在Java中,可以通过两种方式创建线程:继承Thread类和实现Runnable接口。继承Thread类需要重写run()方法,实现Runnable接口需要实现run()方法,并将该Runnable对象传递给Thread类的构造方法。

多线程使用方法一:

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

多线程使用方法二:

实现Runnable接口需要实现run()方法,并将该Runnable对象传递给Thread类的构造方法。

public class MyRunnable extends Runnable {
	@Override
	public void run() {
		// 线程执行的代码
		System.out.println("原神,启动!");
	}
}
	Runnable runnable = new MyRunnable();
	Thread thread = new Thread(runnable);
	thread.start();

4. 使用多线程需要注意的问题

多线程主要是为了提高我们应用程序的使用率。但同时,这会给我们带来很多安全问题例如共享资源的竞争和冲突问题。

如果我们在单线程中以“顺序”(串行–>独占)的方式执行代码是没有任何问题的。但是到了多线程的环境下(并行),如果没有设计和控制得好,就会给我们带来很多意想不到的状况,也就是线程安全性问题。

因为在多线程的环境下,线程是交替执行的,一般他们会使用多个线程执行相同的代码。如果在此相同的代码里边有着共享的变量,或者一些组合操作,我们想要的正确结果就很容易出现了问题。

如果说:当多个线程访问某个类的时候,这个类始终能表现出正确的行为,那么这个类就是线程安全的。

为了避免这些问题,可以使用同步机制,如synchronized关键字和Lock接口,去解决线程安全问题。

你可能感兴趣的:(java,开发语言)