【问题标题】:How to transfer control between threads如何在线程之间转移控制
【发布时间】:2014-02-24 16:10:28
【问题描述】:

我有一个问题,在谷歌上搜索了很长一段时间后我找不到它的答案。 我打算创建一个浏览器应用程序。我想要的是,当 main 方法运行时,我认为它是主浏览器应用程序,并且用户现在可以选择打开多个选项卡。每次打开选项卡时都会启动一个线程,当主应用程序关闭时,所有选项卡都将关闭。每个选项卡(线程)将独立运行,用户可以选择切换选项卡,前一个选项卡继续执行它的操作在用户在新选项卡中工作时执行此操作,并且用户可以根据需要打开任意数量的选项卡。 这是我的代码:

import java.util.Scanner;

public class mainClass 
{
    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        Scanner in = new Scanner(System.in);

        String input="abc";
        String check="true";

        while (check=="true")
        {
            System.out.println("if you want to open new tab write yes");
            input=in.nextLine();
            if (input.equals("yes"))
            {
                System.out.println("if check");
                Thread tab = new myThread();
                tab.start();
                check="true";
            }
            else
            {
                check="false";
                System.out.println("else check");
            }
        }
        return;
    }
}

public class myThread extends Thread 
{
    public myThread()
    {
        setDaemon(true);                                                                                                        
    }

    public void run()
    {
            Scanner in = new Scanner(System.in);

        System.out.println("one thread started");

            System.out.println("enter url to search\n");

            String input=in.nextLine();

    }
}

我的问题是,当用户希望打开线程时,它会打开并完成其任务,而不是等待用户输入它会返回 main 。我想要的是用户应该可以选择在选项卡之间切换。当用户打开一个选项卡时,即使他什么都不做,他也会停留在该选项卡上,当他想切换到另一个选项卡时,他可以这样做。 我如何完全控制一个线程或者我如何睡眠()主线程,直到用户正在处理一个新线程并且当用户希望回到主线程时他可以做到这一点?这可能吗?

【问题讨论】:

  • 有一个yield 方法可能会有所帮助。顺便说一句,我强烈推荐。编程并发教程的洞穴
  • 我不鼓励您手动安排线程,因为这通常会引入性能问题和其他神秘错误。我建议您重新考虑您的体系结构,并将 GUI/选项卡/等视为一个线程,而将其他线程视为在后台保持应用程序状态最新的工作线程。
  • 我实际上根本不会使用线程。多个选项卡不是并行操作的,它们是按顺序操作的,并且单个线程已经可以做到这一点。您并行拥有的是“状态”,但这就是为什么每个实例都有自己的状态的对象。
  • 那我该怎么办?我对线程的所有知识都来自 ivor horton 的一本书,当我用谷歌搜索时,我没有得到任何与我的问题相关的东西或任何可以帮助我解决问题的东西?建议我一个我可以阅读的主题
  • 虽然确实可以按顺序完成,但问题是如何为每个选项卡使用单独的线程来创建浏览器。

标签: java multithreading


【解决方案1】:

首先,代码中的一个基本错误是check=="true" 条件始终为false

改成check.equals("true")可以很快解决,不过还是好好修复吧:

  • String check 更改为boolean check
  • "false" 更改为false
  • "true" 更改为true

其次,这是我对通用线程方案的建议:

步骤#1 - 实现Runnable 接口,而不是扩展Thread 类:

public class MyClass implements Runnable
{
    public MyClass(String input)
    {
        this.input = input;
    }

    public String getOutput()
    {
        return output;
    }

    public void run()
    {
        ...
        output = ...;
    }

    private String input  = null;
    private String output = null;
}

步骤#2 - 将所有线程保存在一个列表中,启动每个线程,然后加入每个线程:

public static ArrayList<String> run(ArrayList<String> inputs,long maxMillisPerThread)
{
    ArrayList<MyClass> myObjects = new ArrayList<MyClass>();
    ArrayList<Thread>  threads   = new ArrayList<Thread>();
    ArrayList<String>  outputs   = new ArrayList<String>();
    for (String input : inputs)
    {
        MyClass myObject = new MyClass(input);
        Thread  thread   = new Thread(myObject);
        myObjects.add(myObject);
        threads.add(thread);
        thread.start();
    }
    for (Thread thread : threads)
    {
        try
        {
            thread.join(maxMillisPerThread);
        }
        catch (Exception error)
        {
        }
    }
    for (MyClass myObject : myObjects)
    {
        outputs.add(myObject.getOutput());
    }
    return outputs;
}

第 3 步 - 为每个线程创建所需的输入,并将其传递给上面的函数。例如:

ArrayList<String> inputs = new ArrayList<String>();
for (int i=0; i<...; i++)
    inputs.add(...);

ArrayList<String> outputs = run(inputs,3000);
for (String output : outputs)
    System.out.println(output);

【讨论】:

  • 我不明白我们的代码或正在做什么以及它将如何帮助我解决我的问题,其次我的循环似乎工作正常
  • 我的一般建议是实现interface Runnable而不是扩展class Thread,将你创建的所有线程保存在线程列表中,一个一个启动所有线程,然后加入所有线程一根一根的穿线。但如果对你没有帮助,我会删除这篇文章。
  • 对不起,如果我是在讽刺,但我认为你没有明白我的意思,或者我可能不够清楚,
  • 正如我所提到的,这是对一般线程方案的建议,而不是针对您的问题的特定解决方案。我在答案中提供的每个编码块上方添加了一个描述行。正如我在之前的评论中提到的,如果它对您的需求完全没有帮助,那么我将删除它。
【解决方案2】:

您将始终拥有一个“主”线程,它通常是唯一用于 UI 操作(绘制组件、处理用户输入等)的线程。您必须将这个线程用于所有选项卡,至少用于 UI 操作。

您可以为每个选项卡创建一个线程,该线程可用于您必须为该选项卡执行的任何计算 操作(即,除了绘制到屏幕之外的几乎所有操作)。您不需要在线程之间“切换”,它们同时运行,您只需要在主线程和这些选项卡线程之间建立某种通信机制。这种通信使用什么主要取决于您使用的 UI 堆栈(swing?android?其他?)。

主线程始终具有某种运行循环机制(由 GUI 工具包提供),您可以使用它来发布要在该线程上运行的事件和动作。 java 中有线程通信实用程序,但是当您谈到 UI 和选项卡时,您确实需要知道您正在为哪个工具包开发并使用它自己的机制。例如,对于 Swing,您将使用 SwingWorkerSwingUtilities#invokeLater

【讨论】:

  • 如何访问主线程以及如何使用主线程向主线程创建的线程发送消息?
  • 我现在没有使用任何 UI 堆栈,我只是希望主线程将任务发送到其他线程中的特定线程?
  • 我真正想要的是在线程之间切换,这可能吗?用户在选择时打开了多个线程,比如说 4 个线程。现在他想转到线程 2,我该怎么做?
  • 其实你不需要这样做; threasd 的要点是它们同时运行。当您的用户切换选项卡时,您的 UI 线程(主线程)也会显示当前选项卡并为其处理输入事件。但是您的其他线程将继续运行,我相信这就是您真正想要的,因为您写道“前一个选项卡继续执行它正在执行的操作,而用户在新选项卡中工作”。关于主线程通信,我将编辑我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多