先说一说多线程的实现方式,有两种,第一种是继承Thread类,第二种是实现Runnable接口。两种方法的区别,第一种使用的时候会有多个线程实例所以多个线程访问的变量不是共享的。
package javabasic;
public class Synchronized extends Thread{
public int a;
@Override
public void run(){
System.out.println(a++);
}
public static void main(String[] args) {
for(int i=0;i<3;i++){
new Synchronized().start();
}
}
}
三个线程访问的a是不同的;
package javabasic;
public class RunnableInstance implements Runnable{
public int a;
public void run(){
System.out.println(a++);
}
public static void main(String[] args) {
RunnableInstance runnable = new RunnableInstance();
for(int i=0;i<3;i++){
new Thread(runnable).start();
}
}
}
打印结果:
0
2
1
因为只有一个RunnableInstance实例,所以a是共享的
接下来进入正题
Synchronized有两种用法:
1.同步代码块
package javabasic;
public class Synchronized extends Thread{
public static String str = “aaa”;
@Override
public void run(){
synchronized(str){
System.out.println("开始");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("结束");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=0;i<3;i++){
new Synchronized().start();
}
}
}
synchronized需要锁住一个对象,这样多个线程就不能同时执行同步代码块的代码,所以前面我们实现Runnable就可以锁住实例的一个成员对象,如果继承Thread则需要锁住一个静态对象。
2.同步方法
package javabasic;
public class Synchronized extends Thread{
@Override
public void run(){
sync();
}
public synchronized void sync(){
System.out.println("开始");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("结束");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=0;i<3;i++){
new Synchronized().start();
}
}
}
这个程序不能防止多个线程访问,因为synchronized方法和下面同步代码块的效果一样
synchronized(this){
//同步代码
}
因为继承Thread,this会指向不同的实例。所以锁住的不是同一个对象。
那么使用同步方法时,还是以实现Runnable的方式来同步。
package javabasic;
public class RunnableInstance implements Runnable{
public int a;
public void run(){
sync();
}
public synchronized void sync(){
System.out.println("开始");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("结束");
}
public static void main(String[] args) {
RunnableInstance runnable = new RunnableInstance();
for(int i=0;i<3;i++){
new Thread(runnable).start();
}
}
}