在Java中多个线程访问方法,为实现同步可以使用synchronized关键字进行对方法和代码块修饰-----同步方法同步代码块。
一、用synchronized修饰方法
业务类
package com.cvicse.thread.sync;
public class Service {
public synchronized void getUsers(){
for (int i =0; i < 15; i++) {
try {
Thread.sleep((long)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("GetUsers:" + i);
}
}
public synchronized void getUserList(){
for (int i =0; i < 15; i++) {
try {
Thread.sleep((long)(Math.random()*3000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("GetUserList:" + i);
}
}
}
线程1类
package com.cvicse.thread.sync;
public class ThreadOne extends Thread{
private Service service = null;
public ThreadOne(Service service) {
this.service = service;
}
@Override
public void run() {
service.getUserList();
}
}
线程2类
package com.cvicse.thread.sync;
public class ThreadTwo extends Thread{
private Service service = null;
public ThreadTwo(Service service) {
this.service = service;
}
@Override
public void run() {
service.getUsers();
}
}
启动类Main.java
package com.cvicse.thread.sync;
public class Main {
public static void main(String args[]) {
Service service = new Service();
ThreadOne t_one = new ThreadOne(service);
ThreadTwo t_two = new ThreadTwo(service);
t_one.start();
t_two.start();
}
}
在Service类中两个方法都被synchronized关键字修饰,执行结果是有顺序的。
在Service类中getUsers方法中去掉synchronized关键字,执行结果是无顺序的。
Java中每个对象都有一把锁或者称为监视器,当多个线程并发访问同一个实例对象的synchronized同步方法时,执行结果是有序的(该对象上锁,此时其它任何线程都无法访问该实例对象的synchronized方法了,只有当前正在访问的线程执行完毕或者抛出异常将锁释放,其他线程才有机会抢夺);当多个线程并发访问同一个实例对象的非synchronized方法时,执行结果是无序的。
在启动类Main.java中修改,如下:
package com.cvicse.thread.sync;
public class Main {
public static void main(String args[]) {
Service service = new Service();
ThreadOne t_one = new ThreadOne(service);
service = new Service();
ThreadTwo t_two = new ThreadTwo(service);
t_one.start();
t_two.start();
}
}
执行程序,结果无序。
二、synchronized修饰静态方法
上述Service业务类getUsers/getUsersList方法添加static修饰
package com.cvicse.thread.sync;
public class Service {
public synchronized static void getUsers(){
for (int i =0; i < 15; i++) {
try {
Thread.sleep((long)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("GetUsers:" + i);
}
}
public synchronized static void getUserList(){
for (int i =0; i < 15; i++) {
try {
Thread.sleep((long)(Math.random()*3000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("GetUserList:" + i);
}
}
}
启动类Main.java
package com.cvicse.thread.sync;
public class Main {
public static void main(String args[]) {
Service service = new Service();
ThreadOne t_one = new ThreadOne(service);
service = new Service();
ThreadTwo t_two = new ThreadTwo(service);
t_one.start();
t_two.start();
}
}
上述执行有序。
这时多个线程并发访问,线程锁定Class的锁。
PS:锁在多线程中使用,当线程并发访问锁定不是同一把对象锁或Class锁时,就会造成不可预期的结果。因此,编写多线程需要注意这点。
记录下来