通过匿名内部类创建线程
问题的出现原因是在代码中使用了两个匿名内部类扩展Thread类,并重写了run()方法。尽管这种写法可能不太容易阅读,但本身并没有问题。
然而,更好的做法是使用Runnable接口。应该将处理/算法与线程策略分离。代码应该修改为如下形式:
public class ThreadLauncher { public static void main(String[] args) { Thread job1 = new Thread(new Job1()); Thread job2 = new Thread(new Job2()); job1.start(); job2.start(); } } public class Job1 implements Runnable { public void run() { // Do some stuff } } public class Job2 implements Runnable { public void run() { // Do some other stuff } }
这样可以多次启动相同的任务。
如果想进一步改进,可以考虑使用ThreadPoolExecutor来处理线程策略。
在上述代码中,通过匿名内部类创建了两个线程,分别是th和th1。这两个线程继承了Thread类,并重写了run方法。当调用start方法时,每个线程都会执行自己的run方法。
匿名内部类是没有具体名称的类,即没有显式的名称,但JVM会将其命名为MyThread3$1来引用其对象。当调用th.getClass()和th.getClass().getSuperclass()时,输出的结果分别为MyThread3$1和Thread。
通过继承Thread类或其子类,可以创建匿名内部类。在代码的第一部分中,继承了Thread类,所以得到的类名是MyThread3$1(因为它是匿名内部类),父类是Thread类(因为继承了它)。因此,可以创建多个匿名内部类来继承Thread类,JVM会将它们命名为MyThread3$1、MyThread3$2、MyThread3$3等等。但是当调用start方法时,每个线程只会执行自己的run方法(通过继承Thread类覆盖了它)。
可以看到,线程th会打印出从0到19的数字,并显示对应的线程ID;线程th1会打印出从50到69的数字,并显示对应的线程ID。这说明每个线程都在执行自己的run方法。
需要注意的是,主线程会逐行执行程序,如果遇到th.start方法,主线程会将子线程发送到执行它的run方法,而主线程会继续执行下一行代码。
文章形成如下:
在上述代码中,通过匿名内部类创建了两个线程,分别是th和th1。这两个线程继承了Thread类,并重写了run方法。当调用start方法时,每个线程都会执行自己的run方法。
匿名内部类是没有具体名称的类,即没有显式的名称,但JVM会将其命名为MyThread3$1来引用其对象。当调用th.getClass()和th.getClass().getSuperclass()时,输出的结果分别为MyThread3$1和Thread。
通过继承Thread类或其子类,可以创建匿名内部类。在代码的第一部分中,继承了Thread类,所以得到的类名是MyThread3$1(因为它是匿名内部类),父类是Thread类(因为继承了它)。因此,可以创建多个匿名内部类来继承Thread类,JVM会将它们命名为MyThread3$1、MyThread3$2、MyThread3$3等等。但是当调用start方法时,每个线程只会执行自己的run方法(通过继承Thread类覆盖了它)。
可以看到,线程th会打印出从0到19的数字,并显示对应的线程ID;线程th1会打印出从50到69的数字,并显示对应的线程ID。这说明每个线程都在执行自己的run方法。
需要注意的是,主线程会逐行执行程序,如果遇到th.start方法,主线程会将子线程发送到执行它的run方法,而主线程会继续执行下一行代码。
使用匿名内部类创建线程的原因是可以简化代码,无需单独创建一个实现Runnable接口的类。然而,这种方式可能导致多个线程同时运行,而不是按顺序一个接一个地运行。解决方法是确保一个线程在另一个线程完成之前不会启动。
以下是问题的解决方案:
Runnable run = new Runnable() { public void run() { try { for (int i = 0; i < 20; i++) { Thread.sleep(1000); System.out.print(i + "\n" + ".."); } } catch (InterruptedException e) { System.out.println(" interrupted"); } } }; Thread thread1 = new Thread(run); Thread thread2 = new Thread(run); thread1.start(); thread1.join(); // 等待第一个线程完成 thread2.start();
在这个解决方案中,我们使用了Thread类的join方法来确保第一个线程执行完毕后再启动第二个线程。这样,我们可以保证线程按顺序一个接一个地运行。
另外,我们注意到代码中使用了synchronized关键字,但并没有实际起到有用的作用。在这种情况下,synchronized关键字可能会导致线程功能不正确。因此,我们可以将其删除,以避免潜在的问题。
通过使用join方法来等待一个线程完成后再启动另一个线程,我们可以解决通过匿名内部类创建线程时可能出现的多个线程同时运行的问题。