使用双线程打印c中的偶数和奇数,即偶数线程和奇数线程
本文关键字:线程 打印 | 更新日期: 2023-09-27 18:23:57
/*我的要求是一个线程应该打印偶数,而另一个线程则应该打印奇数。这些线程应按顺序打印数字(1、2、3、4、5…)
我已经完成了这段代码,但当我对方法countThreadOdd.Start()或countThreadEvend.Start()进行注释时,它不会只打印偶数或奇数。*/
class Program
{
static Object locker = new Object();
static LinkedList<int> number = new LinkedList<int>();
static int counter = 0;
static void Main(string[] args)
{
Thread countThreadOdd = new Thread(oddThread);
Thread countThreadEven = new Thread(evenThread);
//Thread Start
countThreadOdd.Start();
countThreadEven.Start();
//main thread will untill below thread is in exection mode
countThreadOdd.Join(10);
countThreadEven.Join(10);
Console.ReadLine();
}
//Odd Thread
public static void oddThread()
{
for (; counter < 10; )
{
//Lock the another thread to enter in critial area
lock (locker)
{
if (counter % 2 != 0)
{
Console.WriteLine(counter);
counter++;
}
}
}
}
//Even Thread
public static void evenThread()
{
for (; counter < 10; )
{
//Lock the another thread to enter in critial area
lock (locker)
{
if (counter % 2 == 0)
{
Console.WriteLine(counter);
counter++;
}
}
}
}
}
如果您想在两个线程之间交替,可以使用两个AutoResetEvent
对象来执行此操作,如下所示:
public static void oddThread()
{
for (int i = 1; i < 10; i +=2)
{
evenReady.WaitOne();
Console.WriteLine(i);
oddReady.Set();
}
}
public static void evenThread()
{
for (int i = 0; i < 10; i += 2)
{
oddReady.WaitOne();
Console.WriteLine(i);
evenReady.Set();
}
}
如果只想运行其中一个线程,则可以使用ManualResetEvent
来有效地移除所有锁定。
一个完整的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Dmr.Common.Resources;
namespace Demo
{
class Program
{
static EventWaitHandle evenReady;
static EventWaitHandle oddReady;
static void Main(string[] args)
{
bool countOdd = true; // Change these to true/false as wanted.
bool countEven = true;
if (countOdd && countEven)
{
evenReady = new AutoResetEvent(false);
oddReady = new AutoResetEvent(true); // Must be true for the starting thread.
}
else
{
evenReady = new ManualResetEvent(true);
oddReady = new ManualResetEvent(true);
}
Thread countThreadOdd = new Thread(oddThread);
Thread countThreadEven = new Thread(evenThread);
//Thread Start
if (countOdd)
countThreadOdd.Start();
if (countEven)
countThreadEven.Start();
//main thread will untill below thread is in exection mode
if (countOdd)
countThreadOdd.Join();
if (countEven)
countThreadEven.Join();
Console.WriteLine("Done");
Console.ReadLine();
}
public static void oddThread()
{
for (int i = 1; i < 10; i +=2)
{
evenReady.WaitOne();
Console.WriteLine(i);
oddReady.Set();
}
}
public static void evenThread()
{
for (int i = 0; i < 10; i += 2)
{
oddReady.WaitOne();
Console.WriteLine(i);
evenReady.Set();
}
}
}
}
您实际上可以使用Interlocked在线程之间进行通信。Interlocked允许您在两个线程之间同时共享一个变量。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace InterlockedTest
{
class Program
{
private static long _counter = 0;
private static void printEvenTask()
{
while (Interlocked.Read(ref _counter) < 100)
{
if (Interlocked.Read(ref _counter) % 2 == 0)
{
Console.WriteLine(Interlocked.Read(ref _counter));
Interlocked.Increment(ref _counter);
}
}
}
private static void printOddTask()
{
while (Interlocked.Read(ref _counter) < 100)
{
if (Interlocked.Read(ref _counter) % 2 == 1)
{
Console.WriteLine(Interlocked.Read(ref _counter));
Interlocked.Increment(ref _counter);
}
}
}
static void Main(string[] args)
{
Task oddTask = Task.Run(() => printOddTask());
Task evenTask = Task.Run(() => printEvenTask());
oddTask.Wait();
evenTask.Wait();
Console.ReadKey();
}
}
}
static AutoResetEvent evenReady = new AutoResetEvent(true);
static AutoResetEvent oddReady = new AutoResetEvent(false);
static void Main()
{
Thread countThreadOdd = new Thread(oddThread);
Thread countThreadEven = new Thread(evenThread);
countThreadOdd.Start();
countThreadEven.Start();
Console.WriteLine("Done");
Console.ReadLine();
}
public static void oddThread()
{
for (int i = 1; i < 10; i += 2)
{
oddReady.Set();
evenReady.WaitOne();
Console.WriteLine("Odd Thread: " + i);
//oddReady.Set();
}
}
public static void evenThread()
{
for (int i = 0; i < 10; i += 2)
{
oddReady.WaitOne();
evenReady.Set();
Console.WriteLine("Even Thread: " + i);
}
}
我们可以使用共享资源(本例中为整数变量)和Task.Delay(1)来实现这一点,这将允许循环暂停一段时间。
完整程序:
internal class Program
{
int counter = 1;
static void Main(string[] args)
{
var P = new Program();
var t1 = P.OddThread();
var t2 = P.EvenThread();
//Wait for all task to complete
Task.WaitAll(t1, t2);
Console.ReadKey();
}
public async Task OddThread()
{
while (counter < 10)
{
// This delay will allow thread to switch and loop will be paused for some time.
await Task.Delay(1);
//counter is shared between threads, increment the value if it is odd number
if (counter % 2 != 0)
{
Console.WriteLine(counter);
counter++;
}
}
}
//Even Thread
public async Task EvenThread()
{
while (counter < 10)
{
// This delay will allow thread to switch and loop will be paused for some time.
await Task.Delay(1);
//counter is shared between threads, increment the value if it is even number
if (counter % 2 == 0)
{
Console.WriteLine(counter);
counter++;
}
}
}
试试这个方法。它使用任务库。
public class OddEvenThread
{
public static async Task printEvenNumber(int n)
{
for (int i = 1; i <= n; i++)
{
if (i % 2 == 0)
Console.WriteLine(i);
}
await Task.Delay(0);
}
private static async Task printOddNumbers(int n)
{
for (int i = 1; i <= n; i++)
{
if (i % 2 == 1)
Console.WriteLine(i);
}
await Task.Delay(0);
}
public async static Task printNumbers(int n)
{
Task evenNumbers = printEvenNumber(n);
Task oddNumbers = printOddNumbers(n);
List<Task> tasks = new List<Task>() { evenNumbers, oddNumbers };
await Task.WhenAll(tasks);
}
}
使用AutoResetEvent,线程可以相互等待。这里,两个线程写入从1到20的数字:
using System;
using System.Threading;
namespace oddeven
{
class Program
{
static void Main(string[] args)
{
C c = new C();
Thread t1 = new Thread(c.PrintOdd);
Thread t2 = new Thread(c.PrintEven);
t1.Start();
t2.Start();
}
}
class C
{
AutoResetEvent e1 = new AutoResetEvent(true);
AutoResetEvent e2 = new AutoResetEvent(true);
int j = 1;
public void PrintOdd()
{
while (j < 20)
{
if (j % 2 != 0)
{
Console.WriteLine(j);
j++;
}
e1.Set();
e2.WaitOne();
}
}
public void PrintEven()
{
while (j <= 20)
{
e1.WaitOne();
if (j % 2 == 0)
{
Console.WriteLine(j);
j++;
}
e2.Set();
}
}
}
}
为了实现两个线程之间的线程同步,我们在c#中有多种机制,如ManualResetEvent、AutoResetEvent和Task Parallel Library等。
对于DEMO,我使用自动重置事件。
using System;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
public static AutoResetEvent are1 = new AutoResetEvent(false);
public static AutoResetEvent are2 = new AutoResetEvent(false);
public static int index=1;
static void Main(string[] args)
{
//Thread to print odd numbers
Thread tOdd = new Thread(PrintOdd);
//Thread to print even numbers
Thread tEven = new Thread(PrintEven);
tOdd.Start();
tEven.Start();
Console.ReadKey();
}
static void PrintOdd()
{
while(index<=100)
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId}: {index++}");
//sending a signal to print even number
are2.Set();
//block to print odd numbers and wait for getting a signal to print odd even number
are1.WaitOne();
}
}
static void PrintEven()
{
while (index <= 100)
{
//wait for getting a signal to print an even number
are2.WaitOne();
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId}: {index++}");
//sending a signal to print an even number
are1.Set();
}
}
}
}