1

I was trying to understand the CountDownLatch usage, following is the code I am using here,

DecrementRunnable.java

    package com.nirjhar.java.countdownlatchexample;

    import java.util.concurrent.CountDownLatch;

    public class DecrementRunnable implements Runnable {

    private String name;
    private CountDownLatch cdl;

    public DecrementRunnable(String name, CountDownLatch cdl) {
    this.name=name;
    this.cdl=cdl;
    }

    @Override
    public void run() {
        System.out.println("in run method");
    for (int i = 0; i < 6; i++) {
        cdl.countDown();
        System.out.println("counting down "+cdl.getCount());
    }
    //cdl.notifyAll();
    System.out.println("Notified to all");
    }
}

CountDownDemoThread.java

package com.nirjhar.java.countdownlatchexample;

import java.util.concurrent.CountDownLatch;

public class CountDownDemoThread extends Thread {

    private CountDownLatch cdl;

    public CountDownDemoThread(String name, CountDownLatch cdl) {
        this.cdl=cdl;
        setName(name);
    }

    @Override
    public synchronized void start() {

        System.out.println("Task completed ... waiting for other thread to complete their task");
        try {
            cdl.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
        System.out.println("Continuing my tasks ..");
    }
}

Main Program,

package com.nirjhar.java.countdownlatchexample;

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args)
    {
        CountDownLatch cdl=new CountDownLatch(6);
        Thread tDecrementThread=new Thread(new DecrementRunnable("Runnable", cdl));
        CountDownDemoThread cddt=new CountDownDemoThread("thread", cdl);        
        cddt.start();   
        System.out.println("thread 1 started");     
        tDecrementThread.start();
    }
}

In this main program, i was expecting this line "thread 1 started" should get printed once the thread one is started, But here main thread is blocked because of the wait statement in cdl.await() statement in cddt thread. Just wanted to know what is the reason behind this?

4

2 回答 2

3

在您的CountDownThread班级中,我认为您想覆盖run()方法而不是start

代替

公共同步无效开始(){

尝试

公共无效运行(){


原因

cddt 线程中的 cdl.await() 语句中的等待语句。只是想知道这背后的原因是什么?

在这种情况下,您已经覆盖了of 的start方法,Thread因此它不再像往常一样生成一个线程来执行代码。

所以没有产生线程,事实上main线程正在调用cd1.await()而不是cd1线程(你想要的)。这就是main线程被阻塞的原因。

于 2016-03-28T05:30:36.977 回答
0

我认为您应该必须经历线程同步和线程优先级的概念。

1.线程优先级:

java中的每个线程都有一些优先级,它可能是jvm生成的默认优先级或程序员提供的自定义优先级线程优先级的有效范围是1到10,其中1是最小优先级,10是最大优先级线程类定义了以下常量来表示一些标准优先事项:

1.Thread.MIN_PRIORITY----------------1

2.Thread.NORM_PRIORITY------------5

3.Thread.MAX_PRIORITY-------------10

线程调度程序将在分配处理器时使用优先级,具有最高优先级的线程将首先获得机会如果两个线程具有相同的优先级,那么我们不能期望确切的执行顺序,它取决于线程调度程序

Thread 类定义了以下方法来获取和设置线程的优先级:

1.public final int getPriority()

2.public final void setPriority(int p)

注意:允许的值范围从 1 到 10,否则我们会得到运行时异常 IllegalArgumentException

例如:t.setPriority(7):有效

t.setPriority(17):IllegalArgumentException

----------------------------------------默认优先级-------- ------------------------------

仅主线程的默认优先级为 5,但对于所有剩余线程,默认优先级将从父线程继承到子线程,即父线程具有相同优先级的任何优先级都将存在于子线程

--------------------------自定义优先级---------- --------------------------

   class Mythread extends Thread
      {
        public void run()
        {
          for(int i=0;i<=5;i++)
          {
           System.out.println("child thread........");
           }
       }

     }
  public class ThreadDemo
   {
  public static void main(String arg[])
  {
      Mythread t=new Mythread();
     //   t.setPriority(10);----------(1)
      t.start();

       for(int i=0;i<=5;i++)
        {
           System.out.println("main thread........");
        }

     }
  }

如果我们评论第一行,那么主线程和子线程都具有相同的优先级 5,因此我们不能期望执行顺序和准确的输出如果没有评论第一行,那么主线程的优先级为 5,子线程的优先级因此为子线程在这种情况下,将首先获得机会,然后是主线程,输出为:

    Child thread……….

    Child thread……….

    Child thread……….

    Child thread……….

    Child thread……….

    Main thread……….

    Main thread……….

    Main thread……….

    Main thread……….

    Main thread……….

   [NOTE: some platforms won’t provide proper support for thread priority]

2.同步:

Synchronized 是仅适用于方法和块但不适用于类和变量的修饰符。

如果多个线程试图同时对同一个 java 对象进行操作,那么可能会出现数据不一致问题。

为了克服这个问题,如果一个方法或块声明为同步,我们应该使用同步关键字,然后一次只允许一个线程在给定对象上执行该方法或块,这样数据不一致问题就会得到解决。

synchronized 关键字的主要优点是我们可以解决数据不一致的问题,但 synchronized 关键字的主要缺点是它增加了线程的等待时间,并且会产生性能问题,因此如果没有特定要求,则不建议使用 synchronized 关键字。

内部同步概念是通过使用锁来实现的,java中的每个对象都有一个唯一的锁。

每当我们使用同步关键字时,只有锁的概念才会出现。

如果一个线程首先要在给定对象上执行同步方法,它必须获得该对象的锁定。

一旦线程获得锁,就可以在该对象上执行任何同步方法。

一旦方法执行完成,线程就会自动释放锁。内部获取和释放锁由 jvm 和不负责此活动的程序员负责

当一个线程在给定对象上执行同步方法时,其余线程不允许在同一对象上同时执行任何同步方法,但允许其余线程同时执行非同步方法

例子:

Class X
{
  synchronized void m1() {}
  synchronized void m2() {}
   public void m3(){}


  }

在上面的例子中假设线程 T1 开始执行 m1() 因为 T1 首先从 jvm 访问锁,如果同时线程 T2 来执行 m1() 方法和线程 T3 来执行 m2() 方法,那么这两个线程T2 和 T3 将处于等待状态,直到 T1 线程释放锁。

如果线程 T4 来执行 m3() 方法,它将直接执行方法 m3(),因为它不是同步方法。锁的概念是基于对象而不是基于方法实现的

注意:请记住,每个对象都有两个区域:

1.同步区域。

2.非同步区域。

 Class X 

{

   Synchronized();

{

   Where ever we are performing update operation           
  ( Add/remove/delete/replace).

   That is  Where state of object changing.

}

 Non-synchronized()

{

  Where ever state of object won’t be changed, like only read    
 operation is performed.


  }



 }

示例:程序化方法:

  class Display{

    public synchronized void wish(String name){

        for(int i=1;i<=5;i++){
           System.out.print("Good Morning:");

            try{
                 Thread.sleep(2000);
              }

            catch(InterruptedException e){
                 System.out.println("i got Interrupted");

              }

                  System.out.println(name);
          }

      }

}


  class ThreadDemo extends Thread
   {

     Display d;
     String name;
  public ThreadDemo(Display d,String name){

           this.d=d;
           this.name=name;

        }
  public void run(){
         d.wish(name);
      }


}


public class SynchronizedDemo

{

    public static void main(String arg[]){

         Display d=new Display();
         ThreadDemo t1=new ThreadDemo(d,"Avadhoot");
         ThreadDemo t2=new ThreadDemo(d,"Abhishek");
         ThreadDemo t3=new ThreadDemo(d,"Rinkesh");
         ThreadDemo t4=new ThreadDemo(d,"Kushal");
         t1.start();
         t2.start();
         t3.start();
         t4.start();
    }


}

[注意:如果我们没有将 wish(String name) 方法声明为同步,那么所有线程将同时执行,因此我们将得到不规则的输出。

如果我们将 wish(String name) 方法声明为同步,那么一次只允许一个线程在给定的 Display(class) 对象上执行 wish(String name) 方法,因此我们将获得常规输出。]

案例分析:

 public class SynchronizedDemo

 {

     public static void main(String arg[])

     {        
            Display d1=new Display();
            Display d2=new Display();
            Display d3=new Display();
            Display d4=new Display();
         ThreadDemo t1=new ThreadDemo(d1,"Avadhoot");
         ThreadDemo t2=new ThreadDemo(d2,"Abhishek");
         ThreadDemo t3=new ThreadDemo(d3,"Rinkesh");
         ThreadDemo t4=new ThreadDemo(d4,"Kushal");
         t1.start();
         t2.start();
         t3.start();
         t4.start();

     }

  }

即使 wish(String name) 方法是同步的,我们也会得到不规则的输出,因为线程在不同的 java 对象上运行

结论:

如果多个线程在同一个 java 对象上运行,则需要同步。

如果多个线程在多个 java 对象上运行,则不需要同步。


*班级等级锁定:

java中的每个类都有一个唯一的锁,它只不过是类级别的锁。

如果一个线程想要执行一个静态同步方法,那么线程需要类级锁。

一旦线程获得类级锁,就可以执行该类的任何静态同步方法。

一旦方法执行自动完成线程释放锁当线程执行静态同步方法时,其余线程不允许同时执行该类的任何静态同步方法,但允许其余线程同时执行以下方法:

  1. 普通静态方法。

  2. 同步实例方法。

  3. 普通实例方法。

例如:

   Class X
    {
     static synchronized m1(){}
     static synchronized m2(){}
     static m3(){}
     synchronized m4(){}
    m5(){}

   }
于 2016-03-28T06:54:39.983 回答