当前位置: 首页 > 知识库问答 >
问题:

通过扩展在Java中共享同一对象的线程类来创建多个线程

邢飞鸿
2023-03-14

我正在学习多线程的基础知识,并且正在编写一个程序来理解使用两种创建线程的方法之间的区别。

我已经读到,使用Runnable允许多个线程共享同一个对象,并希望在扩展线程时尝试类似的事情。因此,在创建了Demo2的新对象之后,我将引用传递给了线程构造函数(类似于我们在Runnable中所做的)。

当objT1,tT1,tT2将总和的值增加到3时,我达到了我想要达到的目标。但是在打印当前线程的名称时,它只打印demo2。1。我以为将要打印的线程名称是demo2。1,t1,t2,因为我在构造函数中传递了这些名称。

    class Main {
    public static void main(String args[]) {
        Demo1 objR1 = new Demo1();
        Demo2 objT1 = new Demo2("demo2.1");

        Thread tT1 = new Thread(objT1,"t1");
        Thread tT2 = new Thread(objT1,"t2");

        Thread tR1 = new Thread(objR1,"tR1");
        Thread tR2 = new Thread(objR1,"tR2");
    
        objT1.start();
        tT1.start();
        tT2.start();

        tR1.start();
        tR2.start();
    }
}


class Demo1 implements Runnable {

    int sum = 0;

    synchronized void calculate() {
        sum = sum +1;   
    }

    public void run()
    {
        calculate();    
        System.out.print(Thread.currentThread().getName()); 
        System.out.println(" "+sum);
    }
}

class Demo2 extends Thread {

    int sum = 0;

    Demo2(String n) {
        super(n);   
    }
    
    synchronized void calculate() {
        sum = sum +1;       
    }

    public void run()
    {
        calculate();        
        System.out.println(this.getName()+" "+sum);
    }
}

输出:

demo2.1 1
demo2.1 2
demo2.1 3
tR1 1
tR2 2

所以我的问题是——这个片段是否创建了3个线程?如果是,那么为什么每个线程没有3个不同的名称呢。如果没有,那么这些语句的作用是什么。

Demo2 objT1 = new Demo2("demo2.1");
Thread tT1 = new Thread(objT1,"t1");
Thread tT2 = new Thread(objT1,"t2"); 

我知道这一定很琐碎,但我在教程中找不到答案。提前谢谢。

共有1个答案

马哲
2023-03-14

这个片段会创建3个线程吗?

你的程序创建了五个线程。每个线程负责显示的五行输出中的一行。

我认为将打印的线程名称将是demo2.1、t1、t2,因为我在构造函数中传递了这些名称。

这五个线程被命名为“demo2.1”、“t1”、“t2”、“tR1”和“tR2”,但“t1”和“t2”线程永远无法打印自己的名称。这是因为你给了他们每个人一个Runnable委托,它恰好是“demo2.1”线程实例。

“demo2.1”实例的run()方法(类的demo2run()方法)打印自己的名称,但并不总是运行它的线程的名称。

更详细地说:

在这里,您创建了一个新对象,它是一个Demo2,它是一个线程,并且实现了它

Demo2 objT1 = new Demo2("demo2.1")

当你调用obt1.start()时,新线程调用Demo2.run()方法,该方法打印this.getName()

好的,这很简单,但接下来就不那么简单了。

在这里,您创建了另一个新对象,它是一个线程,使用前面的objT1作为其Runnable委托,名为“t1”:

Thread tT1 = new Thread(objT1,"t1");

当你调用tT1.start()时,新线程将调用它的委托的run()方法。它将调用Demo2.run()。但是回想一下,Demo2是一个带有名称的Thread,它的run方法打印自己的名称(实际上是this.getName()),而不是打印正在运行它的线程的名称(这将是Thread.currentThread(). getName())。

扼要重述:

您正在以两种不同的方式使用objT1

  1. 您将其用作线程
  2. 您再次使用它,两次,作为不同线程的委托。

这三次,它都会打印自己的名称,这与将对象用作线程代理的两种情况下运行它的线程的名称不同。

 类似资料:
  • 我正在学习多线程的基础知识,并且正在编写一个程序来理解使用两种创建线程的方法之间的区别。 我已经读到,使用Runnable允许多个线程共享同一个对象,并希望在扩展线程时尝试类似的事情。因此,在创建了Demo2的新对象之后,我将引用传递给了线程构造函数(类似于我们在Runnable中所做的)。 当objT1,tT1,tT2将总和的值增加到3时,我达到了我想要达到的目标。但是在打印当前线程的名称时,它

  • 背景:我正在并行运行自动化测试。使用pom.xml中的分叉,多个浏览器在相同数量的线程中启动,即1个浏览器是1个线程。 中的下面插件创建了与线程(fork)计数相等数量的。 所有这些类都同时并行执行。因此,似乎每当我创建或时,每个线程都会创建自己的这些,因此跨多个线程共享变量的概念是不起作用的。 我只想让一个线程访问“准备测试数据”函数,并将<code>标志 我正在按照教程https://www.

  • 我需要编写一个扩展Thread类的应用程序。我的类在实例化时接受一个整数(即100)<代码>(MyThread myt=新的MyThread(100);) 这个整数将是这个类循环并打印消息的次数。消息应该是“线程正在运行…100”。100将是我传入构造函数的任何数字。如果数字是150,那么输出应该是“线程正在运行…100”。我应该使用main方法来测试这个类。在主线程中,我将启动两个线程,一个线程

  • 我创建了一个可运行的类a,它为我执行一些任务。我使用ExecutorService提交这个类,以便并行执行这些任务。 可运行类A调用另一个对象B,该对象发送一个AsyncFuture请求(future.get()one)。 我将可运行类A的单独对象提交给ExecutorService,但是,类B的对象由bean(单例)引用。这会导致线程执行出现问题吗? 我注意到类A的一些对象没有被任何线程执行。

  • 问题内容: 我是编程新手。我以前尝试过MySQL,但现在是我第一次在python flask网站上使用SQLite。因此,也许我使用的是MySQL语法而不是SQLite,但似乎找不到问题。 这是否意味着我不能在HTML文件中使用名称,电子邮件用户名和密码?我该如何解决? 谢谢。 问题答案: 您的游标“ c”不在同一线程中创建;它可能是在Flask应用运行时初始化的。 您可能希望使用相同的方法生成S

  • 问题内容: 我想像这样在多个线程之间共享一个变量: 我想在主线程和帮助线程之间共享,这是我创建的两个不同的Java类。有什么办法吗?谢谢! 问题答案: 二者并可以参照包含该变量的类。 然后,可以使该变量为 volatile ,这意味着 对该变量的更改在两个线程中立即可见。 有关更多信息,请参见本文。 易变变量 共享已同步的可见性功能,但不共享原子性功能。这意味着线程将自动 查看volatile变量