Java 为什么主线程在启动第一个线程后等待?
我试图理解倒计时锁的用法,下面是我在这里使用的代码 DecrementRunnable.javaJava 为什么主线程在启动第一个线程后等待?,java,java.util.concurrent,countdownlatch,Java,Java.util.concurrent,Countdownlatch,我试图理解倒计时锁的用法,下面是我在这里使用的代码 DecrementRunnable.java package com.nirjhar.java.countdownlatchexample; import java.util.concurrent.CountDownLatch; public class DecrementRunnable implements Runnable { private String name; private Coun
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");
}
}
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 ..");
}
}
主程序,
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();
}
}
在这个主程序中,我希望在线程1启动后打印这一行“thread 1 started”,但是这里的主线程被阻塞了,因为cddt thread中的cdl.await()语句中有wait语句。只是想知道这背后的原因是什么?在您的
倒计时线程
类中,我认为您想重写run()
方法,而不是start
而不是
公共同步的void start(){
试一试
公开募捐{
原因 cdl线程中的wait语句。cddt线程中的wait()语句。只是想知道这背后的原因是什么 在这种情况下,您已经覆盖了
Thread
的start
方法,因此它不再像通常那样生成线程来执行代码
因此没有生成线程,实际上
main
线程正在调用cd1.await()
而不是cd1
线程(您想要的)。这就是main
线程被阻塞的原因。我认为您应该了解线程同步和线程优先级的概念
1.线程优先级:
java中的每个线程都有一些优先级,它可能是jvm生成的默认优先级,也可能是程序员提供的自定义优先级
线程优先级的有效范围是1到10,其中1是最小优先级,10是最大优先级
Thread类定义以下常量以表示某些标准优先级:
1.Thread.MIN_优先级-------1
2.Thread.NORM_优先级----------------5
3.Thread.MAX_优先级-----------------10
线程调度程序将在分配处理器时使用优先级具有最高优先级的线程将首先获得机会
若两个线程具有相同的优先级,那个么我们不能期望精确的执行顺序,这取决于线程调度程序
Thread类定义以下方法来获取和设置线程的优先级:
1.public final int getPriority()
2.公共最终无效设置优先级(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........");
}
}
}
2.同步: Synchronized是仅适用于方法和块的修饰符,但不适用于类和变量 如果多个线程试图同时在同一个java对象上操作,则可能存在数据不一致问题 为了克服这个问题,我们应该使用synchronized关键字,如果一个方法或块声明为synchronized,那么一次只允许一个线程在给定对象上执行该方法或块,这样数据不一致的问题就会得到解决 synchronized关键字的主要优点是我们可以解决数据不一致的问题,但synchronized关键字的主要缺点是它会增加线程的等待时间,并会产生性能问题,因此如果没有具体要求,则不建议使用synchronized关键字 内部同步概念是通过使用锁来实现的,java中的每个对象都有一个唯一的锁 每当我们使用synchronized关键字时,只有锁的概念才会出现在图片中 如果线程想首先在给定对象上执行synchronized方法,它必须获得该对象的锁 一旦线程获得了锁,就可以在该对象上执行任何同步方法 一旦方法执行完成,线程就会自动释放锁。获取和释放锁由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.同步区
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.
}
}
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(stringname)方法是同步的,我们也会得到不规则的输出,因为线程在不同的java对象上操作
结论:
如果多个线程在同一个java对象上运行,则需要同步
如果多个线程在多个java对象上运行,则不需要同步
*级别锁: java中的每个类都有一个唯一的锁,它只是类级锁 如果线程希望执行静态同步方法,则线程需要类级锁
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();
}
}
Class X
{
static synchronized m1(){}
static synchronized m2(){}
static m3(){}
synchronized m4(){}
m5(){}
}