Авторские права принадлежат автору Для любой формы перепечатки, пожалуйста, свяжитесь с автором для получения разрешения и укажите источник.
Разница между потоком и процессом
Каждая программа, работающая в системе, является процессом. Каждый процесс содержит один или несколько потоков. Поток — это набор инструкций или специальный сегмент программы, который может выполняться независимо внутри программы. Его также можно понимать как контекст, в котором выполняется код. Таким образом, потоки — это в основном легкие процессы, которые отвечают за выполнение нескольких задач в рамках одной программы. Обычно операционная система отвечает за планирование и выполнение нескольких потоков.
Использование потоков может помещать задачи в программы, которые занимают много времени. Скорость работы программы может ускориться, а поток более полезен в некоторых ожидающих задачах. В этом случае некоторые ценные ресурсы, такие как память, такие как память и так далее.
Если имеется большое количество потоков, это повлияет на производительность, поскольку операционной системе необходимо переключаться между ними, большему количеству потоков требуется больше памяти, а прерывание потока должно учитывать его влияние на выполнение программы. Обычно данные блочной модели совместно используются несколькими потоками, и это необходимо для предотвращения взаимоблокировки потоков.
Суммировать:Процесс — это совокупность всех потоков, и каждый поток — это путь выполнения в процессе.
Сценарии многопоточных приложений?
Ответ: В основном это отражает многопоточность для повышения эффективности программы.
Например: многопоточная загрузка Thunder, пул соединений с базой данных, пакетная отправка SMS и т. д.
Как создать несколько потоков
Первый наследует класс Thread и переопределяет метод запуска.
//1. 继承thread类,重写run方法,run方法中,需要线程执行代码
class ThreadDemo01 extends Thread {
// run方法中,需要线程需要执行代码
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.print("子id:" + this.getId() + ",");
System.out.print("name:" + getName());
System.out.println("..i:" + i);
System.out.println();
}
}
}
// 1.什么是线程 线程是一条执行路径,每个线程都互不影响。
// 2.什么是多线程,多线程在一个进程中,有多条不同的执行路径,并行执行。目的为了提高程序效率。
// 3.在一个进程中,一定会主线程。
// 4.如果连线程主线程都没有,怎么执行程序。
// 线程几种分类 用户线程、守护线程
// 主线程 子线程 GC线程
public class Test001 {
// 交替執行
public static void main(String[] args) {
System.out.println("main... 主线程开始...");
// 1.创建线程
ThreadDemo01 threadDemo01 = new ThreadDemo01();
// 2.启动线程
threadDemo01.start();
for (int i = 0; i < 10; i++) {
System.out.println("main..i:" + i);
}
System.out.println("main... 主线程结束...");
}
}
Второй реализует интерфейс Runnable и переписывает метод запуска.
class ThreadDemo02 implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(" 子 i:" + i);
}
}
}
// 1.实现runable接口,重写run方法
public class Thread002 {
public static void main(String[] args) {
System.out.println("main... 主线程开始...");
// 创建线程
ThreadDemo02 threadDemo02 = new ThreadDemo02();
Thread t1= new Thread(threadDemo02);
// 启动线程
t1.start();
for (int i = 0; i <10; i++) {
System.out.println("main..i:"+i);
}
System.out.println("main... 主线程结束...");
}
}
Третий способ использования анонимных внутренних классов
public class Thread003 {
public static void main(String[] args) {
System.out.println("main... 主线程开始...");
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(" 子 i:" + i);
}
}
});
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println("main..i:" + i);
}
System.out.println("main... 主线程结束...");
}
}
Лучше использовать класс, который наследуется от Thread или реализует интерфейс Runnable?
Для реализации интерфейса Runnable лучше использовать реализацию, так как интерфейс может продолжать наследоваться, а унаследованный класс не может быть унаследован.
Начальная нить Используемый метод запуска вызова или метод RUN?
Запуск потока выполнения Обратите внимание, что запуск потока вызывает не метод запуска, а метод запуска.
Получить объект потока и его имя
Общие методы API потока | |
---|---|
start() | начать нить |
currentThread() | Получить текущий объект потока |
getID() | Получить идентификатор текущего потока. Номер потока, который начинается с 0. |
getName() | Получить текущее имя потока |
sleep(long mill) | спящая нить |
Останавливаться() | остановить нить, |
Конструктор общего потока | |
---|---|
Нить() | Выделить новый объект Thread |
Тема (имя строки) | Выделяет новый объект Thread с указанным именем, как следует из его имени. |
Поток (Runable r) | Выделить новый объект Thread |
Thread(Runable r, имя строки) | Выделить новый объект Thread |
Нить демона
В Java есть два типа потоков: один — пользовательский, а другой — поток демона.
Пользовательский поток относится к потоку, созданному пользователем.Основной поток останавливается, а пользовательский поток не останавливается.
Поток демона Когда процесс не существует или основной поток останавливается, поток демона также останавливается.
Используйте метод setDaemon(true) для установки в качестве потока демона
public class Test005 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("我是子线程(用户线程)");
}
}
});
// 标识当前方法为守护线程
t1.setDaemon(true);
t1.start();
for (int i = 0; i < 10; i++) {
Thread.sleep(300);
System.out.println("main:i:" + i);
}
System.out.println("主线程执行完毕...");
}
}
Многопоточное рабочее состояние
Поток всегда находится в одном из следующих пяти состояний с момента создания, выполнения до завершения: новое состояние, состояние готовности, состояние выполнения, заблокированное состояние и мертвое состояние.новое состояние
Когда поток создается с помощью оператора new, такого как new Thread(r), поток еще не запущен и находится в новом состоянии. Когда поток находится в зарождающемся состоянии, программа еще не начала выполнение кода в потоке.
состояние готовности
Вновь созданный поток не запускается автоматически.Для выполнения потока необходимо вызвать метод start() потока. Когда объект потока вызывает метод start(), поток запускается.Метод start() создает системные ресурсы для запуска потока и планирует поток для запуска метода run(). Когда метод start() возвращается, поток находится в состоянии готовности.
Поток в состоянии готовности не обязательно немедленно запускает метод run(), поток также должен конкурировать с другими потоками за процессорное время, а поток может быть запущен только в том случае, если процессорное время получено. Потому что в однопроцессорной компьютерной системе невозможно одновременное выполнение нескольких потоков, и одновременно выполняется только один поток. Таким образом, в этот момент может быть несколько потоков в состоянии готовности. Потоки, находящиеся в состоянии готовности, планируются планировщиком потоков системы среды выполнения Java.
Рабочий статус
Когда поток получает процессорное время, он переходит в состояние выполнения и фактически начинает выполнение метода run().
состояние блокировки
В процессе работы поток может переходить в состояние блокировки по разным причинам:
- Поток входит в состояние сна, вызывая метод сна;
- Поток вызывает операцию, которая заблокирована при вводе-выводе, т. е. операция не возвращается к вызывающей стороне до тех пор, пока операция ввода-вывода не будет завершена;
- Поток пытается получить блокировку, удерживаемую другим потоком;
- Поток ожидает условия триггера;
состояние смерти
Потоки могут умереть по двум причинам:
- Метод запуска завершается нормально и естественным образом умирает,
- Необходимое исключение заканчивает метод прогона резьбы внезапной смерти.
Чтобы определить, активен ли поток в данный момент (т. е. готов ли он к выполнению или заблокирован), необходимо использовать метод isAlive. Этот метод возвращает true, если он может выполняться или заблокирован; если поток все еще новый и не может выполняться, или если поток умирает, он возвращает false.
функция метода join()
Когда метод t1.join() выполняется в основном потоке, считается, что основной поток должен отдать право на выполнение t1.
Пример: создайте поток, основной поток может выполняться только после выполнения дочернего потока.
//join
public class Test006 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程,i:" + i);
}
}
});
t1.start();
// 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1
t1.join();
for (int i = 0; i < 10; i++) {
System.out.println("main线程,i:" + i);
}
}
}
приоритет
Современные операционные системы в основном планируют текущие потоки в виде временного подразделения. Количество срезов времени, выделенные поток, определяет, сколько процессорных ресурсов использует нить, а также соответствует концепции приоритета потока. В потоке Java приоритет контролируется приоритетом INT, начиная от 1 до 10, из которых 10 - самое высокое, а значение по умолчанию составляет 5. Ниже приведены некоторые количества и методы приоритета в исходном коде (на основе 1.8).
class PrioritytThread implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().toString() + "---i:" + i);
}
}
}
public class Test008 {
public static void main(String[] args) {
PrioritytThread prioritytThread = new PrioritytThread();
Thread t1 = new Thread(prioritytThread);
Thread t2 = new Thread(prioritytThread);
t1.start();
// 注意设置了优先级, 不代表每次都一定会被执行。 只是CPU调度会有限分配
t2.start();
t1.setPriority(10);
}
}
Метод доходности
Роль метода Thread.yield(): приостановить выполнение текущего потока и выполнить другие потоки. (может не работать)
yield() возвращает текущий запущенный поток в работоспособное состояние, чтобы другие потоки с таким же приоритетом могли выполняться. Следовательно, цель использования yield() состоит в том, чтобы обеспечить правильную ротацию между потоками с одинаковым приоритетом. Однако на практике нет гарантии, что yield() будет уступать, потому что уступающие потоки могут быть повторно выбраны планировщиком потоков.
В заключение:В большинстве случаев yield() переводит поток из состояния выполнения в состояние готовности к выполнению, но это может не иметь никакого эффекта.
пример
Теперь... Когда есть три потока T1, T2 и T3, как вы гарантируете, что T2 выполняется после выполнения T1, а T3 выполняется после выполнения T2.
class T1 implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().toString() + "---i:" + i);
}
}
}
class T2 implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().toString() + "---i:" + i);
}
}
}
class T3 implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().toString() + "---i:" + i);
}
}
}
public class JoinThreadDemo02 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new T1(), "T1");
Thread t2 = new Thread(new T2(), "T2");
Thread t3 = new Thread(new T3(), "T3");
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
}
}
вопросы интервью
- В чем разница между процессом и потоком?
Ответ: Процесс — это совокупность всех потоков, каждый поток — это путь выполнения в процессе, а поток — это просто путь выполнения. - Зачем использовать многопоточность?
Ответ: повысить эффективность программы - Как создать несколько потоков?
Ответ: Наследовать интерфейс Thread или Runnable. - Что лучше: наследовать класс Thread или реализовать интерфейс Runnable?
Ответ: Интерфейс Runnable хорош тем, что он может продолжать наследоваться после реализации интерфейса. Наследование класса Thread больше не может быть унаследовано. - Где вы используете многопоточность?
Ответ: В основном это отражает многопоточность для повышения эффективности программы.
Например: отправка SMS пакетами, многопоточная загрузка Thunder и т. д.