java多线程基础学习(四)

2018-04-22  本文已影响0人  ccq_inori

上一次接触了关键字synchronized,虽然能够使线程同步且不出现脏读的情况,但是它在某些情况下还是有弊端的,如果A线程调用同步方法执行一个长时间的任务,那么B线程则必须等待比较长的时间。这样子就是造成程序执行效率低下。那么该如何使用关键字synchronized呢。在synchronized块中就是同步执行,不在的话就是异步执行。没错,那么我们把它弄成一半异步,一半同步,这样子既能提高程序执行效率又能不出现脏读。

public class Task 
{
    public void dolongTimeTask()
    {
        for(int i=0;i<100;i++)
        {
            System.out.println("nosynchronized threadName="+Thread.currentThread().getName()+" i="+(i+1));
        }
        System.out.println("");
        synchronized (this)
        {
            for(int i=0;i<100;i++)
            {
                System.out.println("synchronized threadName="+Thread.currentThread().getName()+" i="+(i+1));
            }
        }
    }
}
    public static void main(String[] args) 
    {
        Task t=new Task();
        ThreadA ta=new ThreadA(t);
        ta.start();
        ThreadB tb=new ThreadB(t);
        tb.start();
    }
在使用同步synchronized(this)代码块时需要注意,当一个线程访问object的一个synchronized (this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将会被阻塞,这说明synchronized 使用的“对象监视器”是一个。
多个线程调用同一个对象中的不同名称的synchronized 同步方法或者synchronized(this)代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的。

(1)synchronized同步方法
1)对其他synchronized 同步方法或synchronized (this)同步块调用呈阻塞作用
2)同一时间只有一个线程可以执行synchronized同步方法中的代码
(1)synchronized(this)同步代码块
1)对其他synchronized 同步方法或synchronized (this)同步块调用呈阻塞作用
2)同一时间只有一个线程可以执行synchronized(this)同步方法中的代码

还有一点,如果对象监视器不是同一个的话那么结果就是异步调用了,就会交叉运行。

public class Service 
{
    public void Test()
    {
        try
        {
            String anything=new String();
            synchronized (anything) 
            {
                System.out.println("线程的名称:"+Thread.currentThread().getName()+"在 "+System.currentTimeMillis()+"进入同步块");
                Thread.sleep(3000);
                System.out.println("线程的名称:"+Thread.currentThread().getName()+"在 "+System.currentTimeMillis()+"离开同步块");
            }
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
public class Run {

    public static void main(String[] args) 
    {
        Service s=new Service();
        ThreadA ta=new ThreadA(s);
        ta.setName("A");
        ta.start();
        ThreadB tb=new ThreadB(s);
        tb.setName("B");
        tb.start();
    }

}

synchronized(非this对象x)格式的写法是将x对象本身作为"对象监视器",这样子可以得出:

1.当多个线程同时执行synchronized(x){}同步代码块时呈同步效果

2.当其他线程执行x对象中的synchronized同步方法呈同步效果

3.当其他线程执行x对象里面的synchronized(this)代码块时也呈同步效果。

这里举出第二个结论的例子:
public class MyObject 
{
    synchronized public void testMyObjectMethod()
    {
        System.out.println("testMyObjectMethod getlock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
        System.out.println("---------------");
        System.out.println("testMyObjectMethod releaselock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
    }
}
    public void testMethod1(MyObject myobject) 
    {
        synchronized (myobject) 
        {
            try
            {
                System.out.println("testMethod1   getlock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
                Thread.sleep(5000);
                System.out.println("testMethod1   releaseLock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
                
            }
            catch(InterruptedException e)
            {
                
            }
        }
    }
public class ThreadA extends Thread 
{
    private Service s;
    private MyObject m;
    public ThreadA(Service s,MyObject m)
    {
        this.s=s;
        this.m=m;
    }
    public void run()
    {
        s.testMethod1(m);
    }
}
public class ThreadB extends Thread 
{
    private MyObject m;
    public ThreadB(MyObject m)
    {
        this.m=m;
    }
    public void run()
    {
        m.testMyObjectMethod();
    }
}
public class Run {

    public static void main(String[] args) 
    {
        Service s=new Service();
        MyObject m=new MyObject();
        ThreadA ta=new ThreadA(s,m);
        ta.setName("a");
        ta.start();
        ThreadB tb=new ThreadB(m);
        tb.setName("b");
        tb.start();

    }

}
前面的三个结论,一和三都好理解,因为前面一直接触着synchronized关键字。那么只有第二个结论,前面也也没有类似的例子,所以有点理解不了,所以单独拿出来,也是再次理清自己学习多线程的思路。
上一篇 下一篇

猜你喜欢

热点阅读