自定义线程类中的实例变量针对其他线程可以有共与不共享之分,这在多线之间进行交互时是很重要的一个技术点。
下面通过一个实例来看下数据不共享的情况。
public class MyThread extends Thread{
private int count = 5;
public MyThread(String name) {
super();
this.setName(name);//设置线程名称
}
@SuppressWarnings("static-access")
@Override
public void run() {
super.run();
while(count > 0 ) {
count--;
System.out.println(this.currentThread().getName()+""+count);
}
}
}
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
a.start();
b.start();
c.start();
}
}
运行结果:
这就是线程之间数据不共享的情况。
那么,想实现3个线程对同一个count变量进行剪发操作的目的,该如何设计代码呢?
下面就说到了共享数据的情况:
共享数据的情况就是多个线程同时访问同一个变量,比如在现实卖票时,很多个窗口可以同时处理北京到重庆的这趟车所有的票。
下列通过一个实例来看下数据共享情况。
public class MyThread extends Thread {
private int count = 5;
public MyThread() {}
public MyThread(String name) {
// TODO Auto-generated constructor stub
super();
this.setName(name);
}
@SuppressWarnings("static-access")
@Override
synchronized public void run() {
super.run();
count--;
System.out.println("由" + this.currentThread().getName() + "计算count=" + count);
}
}
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread mythread = new MyThread();
Thread a = new Thread(mythread,"A");
Thread b = new Thread(mythread,"B");
Thread c = new Thread(mythread,"C");
a.start();
b.start();
c.start();
}
}
运行结果:
原理:通过在run()方法前加入synchronized关键字,使多个线程在执行run()方法时以排队的方式进行处理。当一个线程在调用run()方法之前,先判断run()方法有没有被上锁,如果上锁,必须等其他线程对run()方法调用结束之后才能执行run()方法。synchronized可以在任意对象或者方法上加锁,而加锁的这段代码被称为“互斥区”或者“临界区”。谁能拿到这把锁,谁就能执行,同时有多个线程去争抢这把锁。
非线程安全指的是多个线程对同一个对象的实例变量进行操作时会出现的值被改变或者值不同步的情况,进而影响程序的执行。