Java 使用信号量从2个线程打印可选输出
我正在学习信号量和多线程的使用,但我有点卡住了。我有两个线程分别打印G和H,我的目标是交替每个线程的输出,以便输出字符串如下所示Java 使用信号量从2个线程打印可选输出,java,multithreading,Java,Multithreading,我正在学习信号量和多线程的使用,但我有点卡住了。我有两个线程分别打印G和H,我的目标是交替每个线程的输出,以便输出字符串如下所示 G H G H G H 这两个类中的每个类都有一个类似于下面的布局 public class ClassA extends Thread implements Runnable{ Semaphore semaphore = null; public ClassA(Semaphore semaphore){ this.sema
G
H
G
H
G
H
这两个类中的每个类都有一个类似于下面的布局
public class ClassA extends Thread implements Runnable{
Semaphore semaphore = null;
public ClassA(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run() {
while(true)
{
try{
semaphore.acquire();
for(int i=0; i<1000; i++){
System.out.println("F");
}
Thread.currentThread();
Thread.sleep(100);
}catch(Exception e)
{
System.out.println(e.toString());
}
semaphore.release();
}
}
}
我得到的结果与我预期的结果相差太大。有人能帮我吗?我是不是误用了信号灯?有什么帮助吗?信号量不能帮助您解决此类任务 据我所知,JVM不保证线程执行的任何顺序。这意味着,如果运行多个线程,一个线程可以在一行中执行多次,并且处理器时间比任何其他线程都多。因此,如果希望线程按特定顺序执行,可以创建一个静态布尔变量,作为线程的切换器。使用wait()和notify()方法将是一种更好的方法,也是我认为最好的方法
import java.io.IOException;
public class Solution {
public static boolean order;
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new ThreadPrint("G", true);
Thread t2 = new ThreadPrint("O", false);
t1.start();
t2.start();
t2.join();
System.out.println("Finish");
}
}
class ThreadPrint extends Thread {
private String line;
private boolean order;
public ThreadPrint(String line, boolean order) {
this.line = line;
this.order = order;
}
@Override
public void run() {
int z = 0;
while (true) {
try {
for (int i = 0; i < 10; i++) {
if (order == Solution.order) {
System.out.print(line + " ");
Solution.order = !order;
}
}
sleep(100);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
因为Thread类已经实现了Runnable。你只能选择一种更适合你的方式
你应该先启动一个线程,然后加入它,而不是反过来
t1.start();
t2.join();
t2.start();
信号量无法帮助您解决此类任务 据我所知,JVM不保证线程执行的任何顺序。这意味着,如果运行多个线程,一个线程可以在一行中执行多次,并且处理器时间比任何其他线程都多。因此,如果希望线程按特定顺序执行,可以创建一个静态布尔变量,作为线程的切换器。使用wait()和notify()方法将是一种更好的方法,也是我认为最好的方法
import java.io.IOException;
public class Solution {
public static boolean order;
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new ThreadPrint("G", true);
Thread t2 = new ThreadPrint("O", false);
t1.start();
t2.start();
t2.join();
System.out.println("Finish");
}
}
class ThreadPrint extends Thread {
private String line;
private boolean order;
public ThreadPrint(String line, boolean order) {
this.line = line;
this.order = order;
}
@Override
public void run() {
int z = 0;
while (true) {
try {
for (int i = 0; i < 10; i++) {
if (order == Solution.order) {
System.out.print(line + " ");
Solution.order = !order;
}
}
sleep(100);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
因为Thread类已经实现了Runnable。你只能选择一种更适合你的方式
你应该先启动一个线程,然后加入它,而不是反过来
t1.start();
t2.join();
t2.start();
正如其他人所指出的,锁本身并不强制执行任何顺序,而且,您无法确定线程何时启动(调用
thread.start()
将在将来某个时候启动线程,但这可能需要一段时间)
但是,您可以使用锁(如信号灯
)来强制执行命令。在这种情况下,您可以使用两个信号量来打开和关闭线程(备用)。这两个线程(或可运行线程
)确实需要事先了解彼此-线程可以“加入”聚会的更动态的方法将更复杂
下面是一个具有可重复结果的可运行示例类(在测试多线程时总是一件好事)。我会让你自己去弄清楚为什么会这样
import java.util.concurrent.*;
public class AlternateSem implements Runnable {
static final CountDownLatch DONE_LATCH = new CountDownLatch(2);
static final int TIMEOUT_MS = 1000;
static final int MAX_LOOPS = 10;
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
try {
AlternateSem as1 = new AlternateSem(false);
AlternateSem as2 = new AlternateSem(true);
as1.setAlternate(as2);
as2.setAlternate(as1);
executor.execute(as1);
executor.execute(as2);
if (DONE_LATCH.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
System.out.println();
System.out.println("Done");
} else {
System.out.println("Timeout");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
final Semaphore sem = new Semaphore(0);
final boolean odd;
AlternateSem other;
public AlternateSem(boolean odd) {
this.odd = odd;
}
void setAlternate(AlternateSem other) { this.other = other; }
void release() { sem.release(); }
void acquire() throws Exception { sem.acquire(); }
@Override
public void run() {
if (odd) {
other.release();
}
int i = 0;
try {
while (i < MAX_LOOPS) {
i++;
other.acquire();
System.out.print(odd ? "G " : "H ");
release();
}
} catch (Exception e) {
e.printStackTrace();
}
DONE_LATCH.countDown();
}
}
import java.util.concurrent.*;
公共类AlternateSem实现Runnable{
静态最终倒计时锁存器完成\u锁存器=新倒计时锁存器(2);
静态最终整数超时\u MS=1000;
静态最终int MAX_循环=10;
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newCachedThreadPool();
试一试{
AlternateSem as1=新的AlternateSem(假);
AlternateSem as2=新的AlternateSem(真);
as1.setAlternate(as2);
as2.setAlternate(as1);
执行人。执行人(as1);
执行人。执行人(as2);
if(完成\u锁存等待(超时\u毫秒,时间单位毫秒)){
System.out.println();
系统输出打印项次(“完成”);
}否则{
System.out.println(“超时”);
}
}捕获(例外e){
e、 printStackTrace();
}最后{
执行者。关机现在();
}
}
最终信号量sem=新信号量(0);
最终布尔奇数;
交替其他;
公共交替序列(布尔奇数){
this.odd=奇数;
}
void setAlternate(AlternateSem other){this.other=other;}
void release(){sem.release();}
void acquire()引发异常{sem.acquire();}
@凌驾
公开募捐{
if(奇数){
其他。释放();
}
int i=0;
试一试{
而(i
正如其他人指出的,锁本身并不强制执行任何顺序,而且,您无法确定线程何时启动(调用thread.start()
将在将来的某个时候启动线程,但这可能需要一段时间)
但是,您可以使用锁(如信号灯
)来强制执行命令。在这种情况下,您可以使用两个信号量来打开和关闭线程(备用)。这两个线程(或可运行线程
)确实需要事先了解彼此-线程可以“加入”聚会的更动态的方法将更复杂
下面是一个具有可重复结果的可运行示例类(在测试多线程时总是一件好事)。我会让你自己去弄清楚为什么会这样
import java.util.concurrent.*;
public class AlternateSem implements Runnable {
static final CountDownLatch DONE_LATCH = new CountDownLatch(2);
static final int TIMEOUT_MS = 1000;
static final int MAX_LOOPS = 10;
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
try {
AlternateSem as1 = new AlternateSem(false);
AlternateSem as2 = new AlternateSem(true);
as1.setAlternate(as2);
as2.setAlternate(as1);
executor.execute(as1);
executor.execute(as2);
if (DONE_LATCH.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
System.out.println();
System.out.println("Done");
} else {
System.out.println("Timeout");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
final Semaphore sem = new Semaphore(0);
final boolean odd;
AlternateSem other;
public AlternateSem(boolean odd) {
this.odd = odd;
}
void setAlternate(AlternateSem other) { this.other = other; }
void release() { sem.release(); }
void acquire() throws Exception { sem.acquire(); }
@Override
public void run() {
if (odd) {
other.release();
}
int i = 0;
try {
while (i < MAX_LOOPS) {
i++;
other.acquire();
System.out.print(odd ? "G " : "H ");
release();
}
} catch (Exception e) {
e.printStackTrace();
}
DONE_LATCH.countDown();
}
}
import java.util.concurrent.*;
公共类AlternateSem实现Runnable{
静态最终倒计时锁存器完成\u锁存器=新倒计时锁存器(2);
静态最终整数超时\u MS=1000;
静态最终int MAX_循环=10;
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newCachedThreadPool();
试一试{
AlternateSem as1=新的AlternateSem(假);
AlternateSem as2=新的AlternateSem(真);
as1.setAlternate(as2);
as2.setAlternate(as1);
执行人。执行人(as1);
执行人。执行人(as2);
if(完成\u锁存等待(超时\u毫秒,时间单位毫秒)){
系统。