标签:
实现线程有两种方法,一种是实现runnable接口,一种是继承Thread线程类。关于这两者的区别是前者只是实现了runnable接口的一个类而已并不是线程,后者继承Thread才是线程
我们来看看代码具体了解下
public class ThreadTest { public static void main(String[] args) { T1 t1=new T1("t1"); T2 t2=new T2("t2"); new Thread(t1).start();//1语句 从测试代码可以看t2才是一个真正意义上的线程对象而t1不是 t2.start();//2语句 这里值得注意的是语句1没执行完时 语句2就开始执行了语句1和语句2时并发执行的 } } class T1 implements Runnable { String name; public T1(String name) { this.name = name; } public void run() { for(int i=0;i<5;i++){ System.out.println("i am "+name); } } } class T2 extends Thread { String name; public T2(String name) { this.name = name; } public void run() { for(int i=0;i<5;i++){ System.out.println("i am "+name); } } }
有了线程我们可以并发处理,但这在一定程度上也会让出现读取脏数据,或者说丢失更新,数据混乱等情况的发生,例如单例模式中两线程同时访问公共单例获取方法 一线程准备给对象引用赋值时,一线程却读取对象的引用为空,也准备创建对象,并把引用赋予局部变量。
这样一来就造成单例对象数据混乱,出现两个实例,和我们的本意相违背。
为了同步,我们引入了synchronized关键字来同步。synchronized关键字既可以用于对象前,也可以用于方法修饰。synchronized(对象引用名) public synchronized void(){}
synchronized关键字保证资源的互斥性,即一段时间之类只能有一个线程访问。线程访问之前必须持有资源锁才能访问。
线程同步简单口述下,就不发代码了。下面我们来看下线程协作。
这里要用到关键字wait() notify() 方法 线程协作我们来看看经典代码生产者 消费者
public class Cooperation { public static void main(String[] args) { SuperMonitor monitor = new SuperMonitor(); new Producer(monitor,200); new Consumer(monitor,200); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } //生产 消费要平衡 生产后再消费,消费完后再生产 由管理员类控制 class SuperMonitor { boolean valueSet = false;//标志是否在生产 int count;//生产的物品总量 public SuperMonitor() { } public synchronized int get() { if(!valueSet) {//生产线程不再生产了,那么消费线程进入等待池,等待生产线程唤醒 try{ wait(); } catch (InterruptedException e) { e.printStackTrace(); } } valueSet = false; System.out.println("已消费"+count+"产品"); notify(); return count; } public synchronized void set(int i) { if(valueSet) {//如何生产线程可以生产了,生产线程进入等待池,等待消费线程唤醒 try{ wait(); } catch (InterruptedException e) { //e.printStackTrace(); } } valueSet = true; count=i; System.out.println("已生产"+count+"产品"); notify(); } } class Producer implements Runnable{ SuperMonitor monitor; int speed;//生产速度相关系数 public Producer(SuperMonitor monitor,int speed) { this.monitor = monitor; this.speed = speed; new Thread(this,"Producer").start(); } public void run() { int i=0; while(true){ monitor.set(++i); try { Thread.sleep((int)Math.random()*speed); } catch (InterruptedException e) { //e.printStackTrace(); } } } } class Consumer implements Runnable{ SuperMonitor monitor; int speed;//消费数量相关系数 public Consumer(SuperMonitor monitor,int speed) { this.monitor = monitor; this.speed = speed; new Thread(this,"Consumer").start(); } public void run() { while(true) { monitor.get(); try { Thread.sleep((int)Math.random()*speed); } catch (InterruptedException e) { e.printStackTrace(); } } } }
这里指的注意的是管理员类里get set 方法需要加锁因为多线程环境下可能找造成同时调用方法,否则会造成异常
标签:
原文地址:http://www.cnblogs.com/kimoyoyo21/p/4760063.html