编写一个线程类,让他访问同一对象的静态资源,实现线程访问的同步
请看下面的代码:public class Test_Sync extends Thread {
Timer timer = new Timer(); //将Timer类设计成Test_Sync类的属性
//重写run()方法
public void run(){
//Thread.currentThread().getName()得到正在执行线程的名字
timer.add(Thread.currentThread().getName());//调用timer的add(String name)方法
}
public static void main(String[] args) {
Test_Sync t1 = new Test_Sync(); //得到线程Test_Sync的实例t1
Test_Sync t2 = new Test_Sync(); //得到线程Test_Sync的实例t2
t1.setName("t1"); //设置线程的名字
t2.setName("t2");
t1.start(); //启动线程
t2.start();
}
} class Timer{
private static int num = 0; //设置共享资源,请注意它的属性是static
//该方法被声明为synchronized
public synchronized void add(String name){
num ++; //每调用一次该方法num加1
try {
Thread.sleep(1); //线程休眠1ms
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+", 你是第"+num+"个访问timer的线程");
}
}这是上面代码的执行结果:
t1, 你是第2个访问timer的线程
t2, 你是第2个访问timer的线程
显然这个结果是错误的:如果将上面的代码作如下修改:public class Test_Sync implements Runnable{
public Timer t = new Timer();
public void run(){
t.add(Thread.currentThread().getName());
}
public static void main(String[] args){
Test_Sync ts1 = new Test_Sync();
Thread t1 = new Thread(ts1);
Thread t2 = new Thread(ts1);
t1.start();
t2.start();
}
}得到正确的结果应该是:
t1, 你是第1个访问timer的线程
t2, 你是第2个访问timer的线程为什么,在第一中的实现方式中add(String name)已被声明为Synchronzied,但是很明显他并没有锁住timer对象,而如果让这个线程类实现Runnable接口而不是继承Thread,则所需的功能就可以实现。所以这个问题引发了我的思考,如果要实现线程同步,对于extends Thread 和 implements Runnable,那个更好?如果两个都可以,那他们分别使用于那些情况?
请看下面的代码:public class Test_Sync extends Thread {
Timer timer = new Timer(); //将Timer类设计成Test_Sync类的属性
//重写run()方法
public void run(){
//Thread.currentThread().getName()得到正在执行线程的名字
timer.add(Thread.currentThread().getName());//调用timer的add(String name)方法
}
public static void main(String[] args) {
Test_Sync t1 = new Test_Sync(); //得到线程Test_Sync的实例t1
Test_Sync t2 = new Test_Sync(); //得到线程Test_Sync的实例t2
t1.setName("t1"); //设置线程的名字
t2.setName("t2");
t1.start(); //启动线程
t2.start();
}
} class Timer{
private static int num = 0; //设置共享资源,请注意它的属性是static
//该方法被声明为synchronized
public synchronized void add(String name){
num ++; //每调用一次该方法num加1
try {
Thread.sleep(1); //线程休眠1ms
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+", 你是第"+num+"个访问timer的线程");
}
}这是上面代码的执行结果:
t1, 你是第2个访问timer的线程
t2, 你是第2个访问timer的线程
显然这个结果是错误的:如果将上面的代码作如下修改:public class Test_Sync implements Runnable{
public Timer t = new Timer();
public void run(){
t.add(Thread.currentThread().getName());
}
public static void main(String[] args){
Test_Sync ts1 = new Test_Sync();
Thread t1 = new Thread(ts1);
Thread t2 = new Thread(ts1);
t1.start();
t2.start();
}
}得到正确的结果应该是:
t1, 你是第1个访问timer的线程
t2, 你是第2个访问timer的线程为什么,在第一中的实现方式中add(String name)已被声明为Synchronzied,但是很明显他并没有锁住timer对象,而如果让这个线程类实现Runnable接口而不是继承Thread,则所需的功能就可以实现。所以这个问题引发了我的思考,如果要实现线程同步,对于extends Thread 和 implements Runnable,那个更好?如果两个都可以,那他们分别使用于那些情况?
解决方案 »
- Java实现PPT的缩略图功能···急急急···在线等···
- 问个简单的问题,一个对象如何拷贝到另一个对象中去?
- 急:Linux下,java调用C++的动态库错误。在线等。。
- 请教java问题
- 为什么我用CardLayout布局时,总是定位在最后,高手请帮我找找问题
- 菜鸟请问:安装JDK后如何配置路径?
- 在菜单项中怎么控制JFrame的关闭
- 有用过excel读写处理包POI的朋友进来看一下。
- 我只是想用HashSet测试随机数的分布密度,请各位看看下面这个程序有什么问题??
- 下周开始课程设计,一点经验没有,不知从何入手,请各位指点。
- java 编写的爬虫 获取HTML源文件
- 高手帮解释一下添加快捷键的原理啊?
public static void main(String[] args) {
Test_Sync t1 = new Test_Sync(); //得到线程Test_Sync的实例t1
new Thread(t1,"t1").start();
new Thread(t1,"t2").start();
//得到线程Test_Sync的实例t2
// t1.setName("t1"); //设置线程的名字
// t2.setName("t2");
// t1.start(); //启动线程
// t2.start();
}
Test_Sync t1 = new Test_Sync(); //得到线程Test_Sync的实例t1
new Thread(t1,"t1").start();
new Thread(t1,"t2").start();
//得到线程Test_Sync的实例t2
// t1.setName("t1"); //设置线程的名字
// t2.setName("t2");
// t1.start(); //启动线程
// t2.start();
}
作如上修改确实实现了线程同步,但我想问您"new Thread(t1,"t2").start();"中t1实际是继承Thread,而非实现Runnable,这和API中new Thread(Runnable target, String name)不同,而编译通过,这是为什么? 谢谢!
class Timer {
private static int num = 0; //设置共享资源,请注意它的属性是static //该方法被声明为synchronized
public synchronized void add(String name) {
System.out.println("执行 add 方法"); //加上开始调用方法打印
num++; //每调用一次该方法num加1
try {
Thread.sleep(1000); //线程休眠1ms sleep改成1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + ", 你是第" + num + "个访问timer的线程");
}
}在运行第一种方法,
结果:
执行 add 方法
执行 add 方法
t1, 你是第2个访问timer的线程
t2, 你是第2个访问timer的线程指所以会这样是因为你有2个Test_Sync类的对象,而每个对象里面又分别new timer()一个新的对象,而synchronized方法对于两个不同对象是不能同步的第二次你的运行结果是正确的,因为你只有一个Test_Sync对象,对于timer对象也只有一个,这样synchronized方法是可以同步的,出现的结果就是你想要的
class Thread implements Runnable
public class Thread implements Runnable {