java多线程1-多线程创建与线程同步

来源:互联网 发布:王者荣耀助手网络错误 编辑:程序博客网 时间:2024/05/17 07:52

Java多线程与线程同步

在Java中实现多线程通过以下2种方式:
1)实现implements 接口Runnable
2) 继承extends Java提供的类Thread,并重写方法run()
一般通过第一种方式来创建多线程.

import org.junit.Test;class Work implements Runnable {    @Override    public void run() {        for(int i = 0; i<3; ++i){            System.out.println("thread "+Thread.currentThread().getName() +" is working " +i);        }       }   }public class RunnableDemo  {    @Test    public void test(){        Work work = new Work();        Thread thread1 = new Thread(work, "thread-1");        Thread thread2 = new Thread(work, "thread-2");        thread1.start();        thread2.start();    }}

运行上述程序,发现线程thread1 和线程thread2交替执行
修改上述代码,增加一个变量count,修改后如下:

    import org.junit.Test;class Work implements Runnable {    int count = 0;    @Override    public void run() {        for(int i = 0; i<3; ++i){            System.out.println("thread "+Thread.currentThread().getName()                     +" is working " +i+" couter is " +(++count));        }    }}public class RunnableDemo  {    @Test    public void test(){        Work work = new Work();        Thread thread1 = new Thread(work, "thread-1");        Thread thread2 = new Thread(work, "thread-2");        thread1.start();        thread2.start();    }}

结果发现两个线程对count这个变量的操作从打印结果来看有时候是一直累加,thread1在thread2操作的基础上进行累加
修改代码,修改如下:

import org.junit.Test;class Work implements Runnable {    int count = 0;    public void add(){     ++count;    }    @Override    public void run() {        add();        for(int i = 0; i<3; ++i){            System.out.println("thread "+Thread.currentThread().getName()                     +" is working " +i+" couter is " +(count));        }    }}public class RunnableDemo  {    @Test    public void test(){        Work work = new Work();        Thread thread1 = new Thread(work, "thread-1");        Thread thread2 = new Thread(work, "thread-2");        thread1.start();        thread2.start();    }}

结果发现两个线程对count这个变量的操作从打印结果来看有时候是一直累加,thread1在thread2操作的基础上进行累加,更重要的是两个线程交替执行,有时候则不是,分析:
比如thread1第一次操作,并执行了add(),紧接着thread2执行第一次操作执行了add(),并执行了打印操作,输出结果count =2,紧接着又返回thread1第一次操作未完成的打印部分代码,也输出 count =2

引入synchronized这个关键字,继续调整代码,调整后代码如下:

import org.junit.Test;class Work implements Runnable {    int count = 0;    public void add(){     ++count;    }    @Override    public void run() {            synchronized(this){            add();            for(int i = 0; i<3; ++i){                add();                System.out.println("thread "+Thread.currentThread().getName()                         +" is working " +i+" couter is " +(count));            }        }        }    }}public class RunnableDemo  {    @Test    public void test(){        Work work = new Work();        Thread thread1 = new Thread(work, "thread-1");        Thread thread2 = new Thread(work, "thread-2");        thread1.start();        thread2.start();    }}

从结果上来看,两个线程不是交替执行的,其中一个线程总是先执行完3次操作,另外一个线程接着执行3次操作,原因是使用了synchronized代码块,synchronized保证了在synchronized代码块中的代码执行的原子性

将上述部分代码封装到一个函数

import org.junit.Test;class Work implements Runnable {    int count = 0;    public void add(){     ++count;    }    public synchronized void loop(){            add();            for(int i = 0; i<3; ++i){                add();                System.out.println("thread "+Thread.currentThread().getName()                         +" is working " +i+" couter is " +(count));            }    }    @Override    public void run() {            loop();        }    }}public class RunnableDemo  {    @Test    public void test(){        Work work = new Work();        Thread thread1 = new Thread(work, "thread-1");        Thread thread2 = new Thread(work, "thread-2");        thread1.start();        thread2.start();    }}

做上述改动后,结果还是顺序执行的,两个线程不是交替执行的,其中一个线程总是先执行完3次操作,另外一个线程接着执行3次操作
又因为synchronize可以放到方法里面,所以loop方法还可以这样写:

public void loop(){            synchronized(this){            add();            for(int i = 0; i<3; ++i){                add();                System.out.println("thread "+Thread.currentThread().getName()                         +" is working " +i+" couter is " +(count));            }            }    }

当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)同步代码块

class Counter implements Runnable{   private int count;   public Counter() {      count = 0;   }   public void countAdd() {      synchronized(this) {         for (int i = 0; i < 5; i ++) {            try {               System.out.println(Thread.currentThread().getName() + ":" + (count++));               Thread.sleep(100);            } catch (InterruptedException e) {               e.printStackTrace();            }         }      }   }   //非synchronized代码块,未对count进行读写操作,所以可以不用synchronized   public void printCount() {      for (int i = 0; i < 5; i ++) {         try {            System.out.println(Thread.currentThread().getName() + " count:" + count);            Thread.sleep(100);         } catch (InterruptedException e) {            e.printStackTrace();         }      }   }   public void run() {      String threadName = Thread.currentThread().getName();      if (threadName.equals("A")) {         countAdd();      } else if (threadName.equals("B")) {         printCount();      }   }}

调用上述代码:

Thread thread1 = new Thread(counter, "A");Thread thread2 = new Thread(counter, "B");thread1.start();thread2.start();

结果:

A:0 B count:1 A:1 B count:2 A:2 B count:3 A:3 B count:4 A:4 B count:5

问题:

问题1:
code snippet1:
Work work = new Work();
Thead thread1 = new Thread(work, “thread1”);
Thread thread2 = new Thread(work, “thread2”);
code snippet2:
Thead thread1 = new Thread(new Work(), “thread1”);
Thread thread2 = new Thread(new Work(), “thread2”);
这两个new Thread 的代码有什么区别?
snippet2 中两次new Work(), 故产生了两个不同的对象,另个对象对应两把对象锁,两把对象锁互不干扰

参考:

http://blog.csdn.net/luoweifu/article/details/46613015

0 0
原创粉丝点击