一: 慎用volatile关键字
volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。但这有一定的限制。当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1。
可以使用synchronized方法来替代。
二:向线程传递数据
可以通过构造方法传入;设置变量及其set方法运行时注入;通过回调函数;
三:从线程返回数据
通过设置变量及其get方法(注意此时要进行检测,get值随着线程运行阶段可能不同);通过回调函数;
四:使用synchronized同步类方法
synchronized修饰方法是类锁定,若修饰非静态方法,只锁定对应对象实例,在两个实例中可能会同时运行;若修饰静态方法,则锁定该类静态域,确保同步。
单件模式中,用到时才创建的时候,需要用到。
如果在类中使用synchronized关键字来定义非静态方法,那将影响这个中的所有使用synchronized关键字定义的非静态方法。如果定义的是静态方法,那么将影响类中所有使用synchronized关键字定义的静态方法。
注意:1,synchronized方法不能被继承;
2,定义接口时不可用synchronized关键字;
3,构造方法不可以用synchronized关键字,但可以使用synchronized块来同步;
4,synchronized的位置可以放在返回类型之前的任意位置;
五:synchronized可以锁定方法或者锁定块,不能锁变量;volatile只能锁简单类型变量。
synchronized锁非静态块时,直接锁类即可;锁静态块需要调用Class对象。
volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。但这有一定的限制。当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1。
可以使用synchronized方法来替代。
/** 该例子显示了volatile失效的情况,可能要多跑几次看出 */
public class JoinThread extends Thread {
public volatile static int n = 0;
public void run() {
for (int i = 0; i < 10; i++)
try {
n++;
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
threads[i] = new JoinThread(); // 建立100个线程
for (int i = 0; i < threads.length; i++)
threads[i].start(); // 运行刚才建立的100个线程
for (int i = 0; i < threads.length; i++)
threads[i].join(); // 100个线程都执行完后继续
System.out.println("n=" + JoinThread.n);
}
}
二:向线程传递数据
可以通过构造方法传入;设置变量及其set方法运行时注入;通过回调函数;
三:从线程返回数据
通过设置变量及其get方法(注意此时要进行检测,get值随着线程运行阶段可能不同);通过回调函数;
四:使用synchronized同步类方法
synchronized修饰方法是类锁定,若修饰非静态方法,只锁定对应对象实例,在两个实例中可能会同时运行;若修饰静态方法,则锁定该类静态域,确保同步。
单件模式中,用到时才创建的时候,需要用到。
如果在类中使用synchronized关键字来定义非静态方法,那将影响这个中的所有使用synchronized关键字定义的非静态方法。如果定义的是静态方法,那么将影响类中所有使用synchronized关键字定义的静态方法。
注意:1,synchronized方法不能被继承;
2,定义接口时不可用synchronized关键字;
3,构造方法不可以用synchronized关键字,但可以使用synchronized块来同步;
4,synchronized的位置可以放在返回类型之前的任意位置;
/**
* synchronized 锁定静态方法与非静态方法
*/
//提供四个被锁定的方法
class ForTest {
static int i = 0;
public static synchronized void staticMethod1() {
System.out.println("staticMethod1");
while (i != 1)
;
System.out.println("staticMethod1 end");
}
public static synchronized void staticMethod2() {
System.out.println("staticMethod2");
while (i != 1)
;
System.out.println("staticMethod2 end");
}
public synchronized void staticMethod3() {
System.out.println("staticMethod3");
while (i != 1)
;
System.out.println("staticMethod3 end");
}
public synchronized void staticMethod4() {
System.out.println("staticMethod4");
while (i != 1)
;
System.out.println("staticMethod4 end");
}
}
//四个调用方法的Runnable
class Runnable1 implements Runnable {
public void run() {
ForTest.staticMethod1();
}
}
class Runnable2 implements Runnable {
public void run() {
ForTest.staticMethod2();
}
}
class Runnable3 implements Runnable {
ForTest f=null;
public Runnable3(ForTest t){
this.f=t;
}
public void run() {
f.staticMethod3();
}
}
class Runnable4 implements Runnable {
ForTest f=null;
public Runnable4(ForTest t){
this.f=t;
}
public void run() {
f.staticMethod4();
}
}
public class MyThread1 {
public static void main(String[] args) throws Exception {
ForTest t=new ForTest();
Thread t1=new Thread(new Runnable1());
Thread t2=new Thread(new Runnable2());
Thread t3=new Thread(new Runnable3(t));
Thread t4=new Thread(new Runnable4(t));
System.out.println("start");
t1.start();
t2.start();
t3.start();
t4.start();
Thread.sleep(1000);
t.i=1;
System.out.println("main end");
}
}
五:synchronized可以锁定方法或者锁定块,不能锁变量;volatile只能锁简单类型变量。
synchronized锁非静态块时,直接锁类即可;锁静态块需要调用Class对象。
public class SyncBlock {
public static void method1() { //锁静态块
synchronized (SyncBlock.class) {
}
}
public static synchronized void method2() {} //锁静态方法
public void method3() { //锁非静态块
synchronized (SyncBlock.class) {
}
}
public void method5() {
synchronized (this) {
}
}
public synchronized void method4() {} //锁非静态方法
}