在Java中,一个对象能否创建多个线程?

3

我对多线程还不熟悉,在练习时写了以下代码。每次调用createThread方法时,我希望它创建一个新的线程。然而,使用下面给出的代码时,每次调用createThread方法时,我都会得到相同的线程一遍又一遍地运行。使用相同的对象是否可以创建新线程?显然不行,但只是想确认我是否存在不知道的方法。

public class ThreadStartRunnable implements Runnable {

    private Thread t;
    /*
     ThreadStartRunnable(String name) {
         t = new Thread(this, name);
        t.start();
        }
     */
       private Thread createThread(String name){

         t = new Thread(this,name);
         t.start();
         return t;
     }

    /**
     * @Override run
     * 
     */
    public void run() {

        for(int i=0;i<=5;i++)
        {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("The current Thread is " + t.getName() + " and thread ID is " + t.getId());
        }
    }
    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args)  {
        // TODO Auto-generated method stub

        Thread t = Thread.currentThread();
        //new ThreadStartRunnable("User 1");
        //new ThreadStartRunnable("User 2");
        //ThreadStartRunnable c = new ThreadStartRunnable();
        ThreadStartRunnable t1 = new ThreadStartRunnable();

        t1.createThread("Child 1");
        t1.createThread("Child 2");

        for(int i=0;i<=5;i++)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("The cirrent Thread is " + t.getName()+ " and thread ID is " + t.getId());
        }




    }

}

输出:

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是main,线程ID为1

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是main,线程ID为1

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是Child 2,线程ID为9

当前线程是main,线程ID为1

当前线程是main,线程ID为1

当前线程是main,线程ID为1

当前线程是main,线程ID为1


你的代码对我有效。尝试创建5个不同的线程。 - washcloth
你正在失去对“Child 1”线程的引用。你想要创建多个ThreadStartRunnable实例,或者将你的代码更改为在单个ThreadStartRunnable实例中有多个Thread - wns349
@ExcelledProducts 不,不是这样的。它运行了五次,但请看子线程的名称和ID。 - Sameer
@wns349 t = new Thread(this, name); 显示稍后处理,但实际上并没有。我不想创建ThreadStartRunnable的多个实例。 - Sameer
这并不是真正回答你的问题,但如果你想执行多线程任务,你应该研究一下 java.util.concurrent 包提供的 Executors 和 ExecutorService。 - jgitter
显示剩余6条评论
4个回答

3
它总是显示“Child 2”的原因是因为您正在打印“Thread t”成员的名称,这是最后创建的线程的名称。
替换:
System.out.println("The current Thread is " + t.getName() + " and thread ID is " + t.getId());
用以下代码替换:
System.out.println("The current Thread is " + Thread.currentThread().getName() + " and thread ID is " + Thread.currentThread().getId());
否则,可以使用相同的可运行程序: 使用相同的可运行程序初始化两个线程

2

将run方法中的代码更改为显示当前线程名称:

System.out.println("The current Thread is " + Thread.currentThread().getName() + " and thread ID is " + Thread.currentThread().getId());

每次创建新的Thread时,都会覆盖实例变量t,因此不能安全地使用它来跟踪线程名称和ID。

您,先生,是个天才 :) - Sameer
我还有一个基本问题,我们可以将线程t的语句声明为静态的吗?我们也可以将createThread语句声明为静态的吗?当我尝试这样做时,调用start方法时run方法没有执行。 - Sameer
1
是的,这是可能的。然后,您还需要将线程初始化更改为类似于此的内容:t = new Thread(new ThreadStartRunnable(),name);。另外,我真的不明白为什么您需要变量t?您可以将其设置为本地变量。 - hoaz

1
你可能想要使用 ExecutorService 在单个对象中运行多个线程。
看下面的代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test1 {
    private ExecutorService threads;

    public Test1(int poolSize) {
        // Use fixed-size thread pool
        threads = Executors.newFixedThreadPool(poolSize);
    }

    public void createThread(String name) {
        threads.execute(new MyThread(name)); // Create MyThread
    }

    public class MyThread extends Thread {
        // Constructor passing thread name
        public MyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i <= 5; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("The current Thread is " + super.getName()
                        + " and thread ID is " + super.getId());
            }
        }
    }

    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        Test1 t1 = new Test1(3);

        t1.createThread("Child 1");
        t1.createThread("Child 2");

        for (int i = 0; i <= 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("The cirrent Thread is " + t.getName()
                    + " and thread ID is " + t.getId());
        }
    }
}

3
没有回答问题。 - RokL

1
问题在于您正在使用单个引用 this.t 存储线程,然后当您创建第二个线程时,会覆盖这个单个引用,使其指向第二个线程。因此,当您打印 t.getName() 时,它将引用第二个线程。
如果您希望代码按预期运行,请像这样打印当前线程而不是 t:
System.out.println("The current Thread is " + Thread.currentThread().getName() + " and thread ID is " + Thread.currentThread().getId());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接