1、实现Runnable接口
同步代码块
使用synchronized关键字进行同步代码块的声明,但是在使用此操作时必须明确的指出到底要锁定的是哪个对象,一般是以当前对象为主.
synchronized(对象){ //一般都是讲this锁定
//锁定对象
}
使用同步代码块解决:
package org.dennist.thread.demo;
/**
*
* TicketThreadR.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-24 下午02:29:23
*
* TODO : class TicketThreadR.java is used for ...
*
*/
public class TicketThreadR implements Runnable{
private int num = 5; //总共票数设定为5张
@Override
public void run() {
for(int i=0; i<10; i++){
//使用同步代码块
synchronized (this) {
try {
Thread.sleep(300); //休息300毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
if(this.num>0){
//打印买票信息
System.out.println(Thread.currentThread().getName() + "买票: " + this.num--);
}
}
}
}
public static void main(String[] args) {
TicketThreadR ticketThread = new TicketThreadR();
new Thread(ticketThread,"售票口一").start(); //线程一
new Thread(ticketThread,"售票口二").start(); //线程二
new Thread(ticketThread,"售票口三").start(); //线程三
}
}
同步方法
同步方法是在方法上增加synchronized关键字修饰
上面的问题使用同步代码块解决
package org.dennist.thread.demo;
/**
*
* TicketThreadR.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-24 下午02:29:23
*
* TODO : class TicketThreadR.java is used for ...
*
*/
public class TicketThreadR implements Runnable{
private int num = 5; //总共票数设定为5张
@Override
public void run() {
for(int i=0; i<10; i++){
sale(); //调用同步方法
}
}
//使用同步方法
public synchronized void sale(){
try {
Thread.sleep(300); //休息300毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
if(this.num>0){
//打印买票信息
System.out.println(Thread.currentThread().getName() + "买票: " + this.num--);
}
}
public static void main(String[] args) {
TicketThreadR ticketThread = new TicketThreadR();
new Thread(ticketThread,"售票口一").start(); //线程一
new Thread(ticketThread,"售票口二").start(); //线程一
new Thread(ticketThread,"售票口三").start(); //线程一
}
}
2、继承Thread类
错误分析:
class Thread2 extends Thread {
int n = 100;
public void run() {
method();
}
public synchronized void method() {
while (n > 0) {
System.out.println(n--);
}
}
}
class Test {
public static void main(String[] args) {
Thread2 t1 = new Thread2();
Thread2 t2 = new Thread2();
Thread2 t3 = new Thread2();
Thread2 t4 = new Thread2();
t1.start();
t2.start();
t3.start();
t4.start();
}
}
以下这段代码无法达到同步的效果,虽然method方法使用了synchronized修饰,但每次都是通过new关键字出来的是不同的对象,他们的监视器对象不同,是吧?那么如何让这四个对象(t1、t2、t3、t4)使用同一个监视器来达到同步效果呢?
class SomeThread extends Thread {
Object locker;
public SomeThread(Object locker) {
this.locker = locker;
}
public void run() {
synchronized(locker) { //locker共同访问的资源就可以了
//do something here
}
}
}
public class Test {
public static void main(String[] args) {
Object locker = new Object();
Thread[] t = new Thread[10];
for (int i=0; i<t.length; i++) {
t[i] = new SomeThread(locker); //把共同资源对象传给线程
t[i].start();
}
}
}
只要锁住共同访问的资源对象就可以了,如果想偷懒,直接synchronized(SomeThread.class),锁住类对象,不过锁类对象牺牲太大,性能有所下降,所以轻易不锁类对象。