Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用信号量从2个线程打印可选输出_Java_Multithreading - Fatal编程技术网

Java 使用信号量从2个线程打印可选输出

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
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毫秒,时间单位毫秒)){
系统。