了解生产者消费者问题的线程| Java
原文:https://www . geesforgeks . org/understanding-threads-on-producer-consumer-problem-Java/
线程是执行的一部分,即它是程序中独立的执行路径。一个程序可以有多个线程,这就产生了多线程的概念。我们必须使用 java.lang.Thread 类才能使用一个线程来执行特定的任务。在本文中,让我们通过一个程序来看看线程的实现。 每当一个程序被执行时,JVM 首先检查“Main”方法的存在。如果方法存在,默认情况下它会创建一个线程,这个线程被称为“主线程”,因为它负责执行主方法中存在的语句。一个线程可以处于多种状态,本文对此进行了讨论。 创建线程有两种方式。它们是:
- 通过为线程类创建一个对象。
- 通过使用可运行接口。
通过扩展 Thread 类来创建线程:我们创建了一个扩展 java.lang.Thread 类的类。此类覆盖线程类中可用的 run() 方法。一根线在运行()方法中开始它的生命。我们创建一个线程类的对象,调用 start() 方法开始执行一个线程。 Start() 调用线程对象上的 run() 方法。让我们来看一个使用线程寻找阶乘的例子:
Java 语言(一种计算机语言,尤用于创建网站)
// Java program to find the factorial
// of a number by the implementation
// of threads using thread class
class ThreadImplement extends Thread {
static int fact = 1;
// Overriding the run method
// to find the factorial of
// a number 5
public void run()
{
// Loop to compute the factorial
for (int i = 1; i <= 5; i++)
fact = fact * i;
System.out.println(fact);
}
}
// Class to create a thread and
// compute the factorial
public class GFG {
public static void main(String[] args)
{
// Creating an object of the
// thread class
Thread t1
= new Thread(new ThreadImplement());
// Computing the above class
t1.start();
}
}
Output:
120
通过实现可运行接口创建线程:线程类实现可运行接口,可运行接口只包含 run() 方法。线程类中有近 37 种方法,但我们通常使用 22 种。所有需要由线程执行的任务都必须放在 run()方法中,也就是说,我们必须重写 run()方法。为了开始一个线程,我们必须使用 start() 方法。启动线程后,该线程将执行 run() 方法中存在的语句。让我们使用可运行的接口 实现相同的阶乘程序
Java 语言(一种计算机语言,尤用于创建网站)
// Java program to find the factorial
// of a number by the implementation
// of threads using runnable interface
class ThreadImplement implements Runnable {
static int fact = 1;
// Overriding the run method
// to find the factorial of
// a number 5
public void run()
{
// Loop to compute the factorial
for (int i = 1; i <= 5; i++)
fact = fact * i;
System.out.println(fact);
}
}
// Class to create a thread and
// compute the factorial
public class GFG {
public static void main(String[] args)
{
// Creating an object of the
// thread class
Thread t1
= new Thread(new ThreadImplement());
// Computing the above class
t1.start();
}
}
Output:
120
Java 中的多线程:在计算中,生产者-消费者问题(也称为有界缓冲区问题)是多进程同步问题的经典例子。这个问题描述了两个进程,生产者和消费者,它们共享一个公共的、固定大小的缓冲区作为队列。
- 生产者的工作是生成数据,将其放入缓冲区,然后重新开始。
- 与此同时,消费者正在消耗数据(即从缓冲区中删除数据),一次一个。
在这个问题中,我们需要两个线程,线程 t1(产生数据)和线程 t2(消耗数据)。然而,这两个线程不应该同时运行。
下面是生产者-消费者问题的实现:
Java 语言(一种计算机语言,尤用于创建网站)
// Java program to implement the
// producer consumer's problem
import java.lang.Thread;
// Producer class which extends the
// thread
class Producer extends Thread {
// Creating a string buffer
StringBuffer buffer;
boolean dp = false;
// Initializing the string buffer
Producer()
{
buffer = new StringBuffer(4);
}
// Overriding the run method
public void run()
{
synchronized (buffer)
{
// Adding the data into the
// buffer
for (int i = 0; i < 4; i++) {
try {
buffer.append(i);
System.out.println("Produced " + i);
}
catch (Exception e) {
e.printStackTrace();
}
}
// Notifying the buffer
System.out.println("Buffer is FUll");
buffer.notify();
}
}
}
// Consumer class which extends
// the thread
class Consumer extends Thread {
// Creating the object of the
// producer class
Producer p;
// Assigning the object of the
// producer class
Consumer(Producer temp)
{
p = temp;
}
// Overriding the run method
public void run()
{
// Controlling the access of the
// buffer to the shared producer
synchronized (p.buffer)
{
try {
p.buffer.wait();
}
catch (Exception e) {
e.printStackTrace();
}
// Printing the values of the string buffer
// and consuming the buffer
for (int i = 0; i < 4; i++) {
System.out.print(p.buffer.charAt(i) + " ");
}
System.out.println("\nBuffer is Empty");
}
}
}
// Main class to implement the
// Producer Consumer problem
class GFG {
public static void main(String args[])
{
// Initially, there needs to be some data
// in order to consume the data. So,
// Producer object is created first
Producer p = new Producer();
// Sending this producer object
// into the consumer
Consumer c = new Consumer(p);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
// Since from the producer object,
// we have already produced the data.
// So, we start by consuming it.
t2.start();
t1.start();
}
}
Output:
Produced 0
Produced 1
Produced 2
Produced 3
Buffer is FUll
0 1 2 3
Buffer is Empty
生产者消费者没有同步的问题:上面的代码效率不高,因为 CPU 资源没有得到有效利用。线程正在等待处于等待状态的缓冲区。相反,我们可以通过终止这些线程并重新创建它们来有效地利用它们。也就是:
- 我们创建一个线程来产生数据。
- 一旦缓冲区满了,我们将终止该线程。
- 创建另一个线程来使用数据(此时生产者线程是死的)。
- 一旦缓冲区为空,消费者线程终止,生产者线程被创建并产生数据(此时消费者线程是死的)。
以下是上述方法的实现:
Java 语言(一种计算机语言,尤用于创建网站)
// Java program to implement the
// producer consumer's problem
// without using synchronization
import java.lang.Thread;
// Producer class which extends the
// thread
class Producer extends Thread {
// Creating a string buffer
StringBuffer buffer;
// Initializing the string buffer
Producer()
{
buffer = new StringBuffer(4);
}
// Overriding the run method
public void run()
{
// Loop to add data into the
// buffer
for (int i = 0; i < 4; i++) {
try {
buffer.append(i);
System.out.println("Produced " + i);
}
catch (Exception e) {
// Exception is returned when
// the buffer is not accessible
e.printStackTrace();
}
}
System.out.println("Buffer is FUll");
// Creating a consumer object after
// execution of the above method.
// Here, this keyword refers to
// the current object of the
// producer. This object is passed
// into the consumer to access the
// created buffer
Consumer c = new Consumer(this);
}
}
// Consumer class which extends
// the thread
class Consumer extends Thread {
Producer p;
Thread t2;
// Constructor to get the
// producer object
Consumer(Producer temp)
{
p = temp;
// Creating a new thread for
// the object
t2 = new Thread(this);
t2.start();
}
// Overriding the run method
public void run()
{
try {
// Printing the string buffer and
// consuming it
for (int i = 0; i < 4; i++) {
System.out.print(p.buffer.charAt(i) + " ");
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("\nBuffer is Empty");
}
}
// Main class to implement the
// Producer Consumer problem
class Efficiency {
public static void main(String args[])
{
// Producer object is created and
// passed into the thread.
Producer p = new Producer();
Thread t1 = new Thread(p);
// Here, instead of the same
// thread waiting, a new thread
// is created in the constructor
// of the consumer class
t1.start();
}
}
Output:
Produced 0
Produced 1
Produced 2
Produced 3
Buffer is FUll
0 1 2 3
Buffer is Empty
修改生产者消费者的问题:上述方法可以进一步改进,因为生产者和消费者正在使用相同的缓冲区。因此,不要使用多个线程,而是使用一个线程,这样最初缓冲区是空的,并且创建的线程充当生产者。一旦缓冲区满了,这个线程就充当一个使用者,消耗数据。然而,我们需要避免僵局。
以下是上述方法的实现:
Java 语言(一种计算机语言,尤用于创建网站)
// Java program to implement the
// producer consumer's problem
// using single thread
import java.lang.Thread;
// Producer class which extends the
// thread
class Producer extends Thread {
// Creating a string buffer
StringBuffer buffer;
// Variable to avoid the deadlock
boolean dp = false;
Thread t1;
Producer()
{
// Initializing the buffer
buffer = new StringBuffer(4);
// Creating a new thread with
// the current object
t1 = new Thread(this);
t1.start();
}
// Overriding the run method
public void run()
{
// Loop to produce the
// data and add it to
// the buffer
for (int i = 0; i < 4; i++) {
try {
buffer.append(i);
System.out.println("Produced " + i);
}
catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Buffer is FUll");
// Creating a consumer object
// by passing the current
// producer object
Consumer c = new Consumer(this);
// Reinitializing the thread
// with the new value of the
// consumer object
t1 = new Thread(c);
t1.start();
}
}
// Consumer class which extends
// the thread
class Consumer extends Thread {
Producer p;
// Constructor to initialize
// with the producer object
Consumer(Producer temp)
{
p = temp;
}
// Overriding the run method
public void run()
{
try {
// Loop to print the buffer and
// consume the values
for (int i = 0; i < 4; i++) {
System.out.print(p.buffer.charAt(i) + " ");
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("\nBuffer is Empty");
}
}
// Main class to implement the
// Producer Consumer problem
class GFG {
public static void main(String args[])
{
// Creating the object of the
// producer
Producer p = new Producer();
}
}
Output:
Produced 0
Produced 1
Produced 2
Produced 3
Buffer is FUll
0 1 2 3
Buffer is Empty
版权属于:月萌API www.moonapi.com,转载请注明出处