以此文来反驳网上一片博文:Java中Runnable和Thread的区别
http://blog.chinaunix.net/uid-20665441-id-310538.html,这两个哪个是原创不分了
Runnable并不能解决资源共享。
废话不多说,上代码:
public class Demo implements Runnable {
private static final Logger logger = Logger.getLogger(Demo.class);
String name;
static Integer tickets = 20;
public Demo(String name) {
this.name = name;
}
public void run() {
for (int i = 1; i <= 20; i++) {
if (tickets > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
logger.info("我取票了" + ": " + tickets);
tickets -= 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
logger.info("==========我取走了" + ": " + tickets);
}
}
}
public static void main(String[] args) throws IOException {
Demo demo = new Demo("hello");
new Thread(demo).start();
new Thread(demo).start();
new Thread(demo).start();
}
}
结果:
[Thread-1] 我取票了: 20
[Thread-2] 我取票了: 20
[Thread-0] 我取票了: 20
[Thread-1] ==========我取走了: 17
[Thread-2] ==========我取走了: 17
[Thread-0] ==========我取走了: 17
[Thread-1] 我取票了: 17
[Thread-2] 我取票了: 16
[Thread-0] 我取票了: 15
[Thread-1] ==========我取走了: 14
[Thread-2] ==========我取走了: 14
[Thread-0] ==========我取走了: 14
[Thread-1] 我取票了: 14
[Thread-2] 我取票了: 14
[Thread-0] 我取票了: 12
[Thread-1] ==========我取走了: 11
[Thread-2] ==========我取走了: 11
[Thread-0] ==========我取走了: 11
[Thread-1] 我取票了: 11
[Thread-2] 我取票了: 10
[Thread-0] 我取票了: 9
[Thread-1] ==========我取走了: 8
[Thread-2] ==========我取走了: 8
[Thread-0] ==========我取走了: 8
[Thread-2] 我取票了: 8
[Thread-1] 我取票了: 8
[Thread-0] 我取票了: 6
[Thread-2] ==========我取走了: 5
[Thread-1] ==========我取走了: 5
[Thread-0] ==========我取走了: 5
[Thread-1] 我取票了: 5
[Thread-2] 我取票了: 5
[Thread-0] 我取票了: 3
[Thread-1] ==========我取走了: 2
[Thread-2] ==========我取走了: 2
[Thread-0] ==========我取走了: 2
[Thread-2] 我取票了: 2
[Thread-1] 我取票了: 2
[Thread-0] 我取票了: 0
[Thread-1] ==========我取走了: -1
[Thread-2] ==========我取走了: -1
[Thread-0] ==========我取走了: -1
从上面结果看到,最后出现负数,所以
仅仅依靠Runnable是不能解决资源共享问题的。
那么如何解决呢?
办法1. 同步run()方法
public synchronized void run()
输出结果为:
[Thread-0] 我取票了: 20
[Thread-0] ==========我取走了: 19
[Thread-0] 我取票了: 19
[Thread-0] ==========我取走了: 18
[Thread-0] 我取票了: 18
[Thread-0] ==========我取走了: 17
[Thread-0] 我取票了: 17
[Thread-0] ==========我取走了: 16
[Thread-0] 我取票了: 16
[Thread-0] ==========我取走了: 15
[Thread-0] 我取票了: 15
[Thread-0] ==========我取走了: 14
[Thread-0] 我取票了: 14
[Thread-0] ==========我取走了: 13
[Thread-0] 我取票了: 13
[Thread-0] ==========我取走了: 12
[Thread-0] 我取票了: 12
[Thread-0] ==========我取走了: 11
[Thread-0] 我取票了: 11
[Thread-0] ==========我取走了: 10
[Thread-0] 我取票了: 10
[Thread-0] ==========我取走了: 9
[Thread-0] 我取票了: 9
[Thread-0] ==========我取走了: 8
[Thread-0] 我取票了: 8
[Thread-0] ==========我取走了: 7
[Thread-0] 我取票了: 7
[Thread-0] ==========我取走了: 6
[Thread-0] 我取票了: 6
[Thread-0] ==========我取走了: 5
[Thread-0] 我取票了: 5
[Thread-0] ==========我取走了: 4
[Thread-0] 我取票了: 4
[Thread-0] ==========我取走了: 3
[Thread-0] 我取票了: 3
[Thread-0] ==========我取走了: 2
[Thread-0] 我取票了: 2
[Thread-0] ==========我取走了: 1
[Thread-0] 我取票了: 1
[Thread-0] ==========我取走了: 0
办法2. 同步tickets?这种方法貌似很行哦(⊙o⊙),Really?
public void run() {
for (int i = 1; i <= 20; i++) {
synchronized (tickets) {
if (tickets > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
logger.info("我取票了" + ": " + tickets);
tickets -= 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
logger.info("==========我取走了" + ": " + tickets);
}
}
}
}
输出结果为:
[Thread-0] 我取票了: 20
[Thread-0] ==========我取走了: 19
[Thread-2] 我取票了: 19
[Thread-0] 我取票了: 19
[Thread-2] ==========我取走了: 17
[Thread-0] ==========我取走了: 17
[Thread-2] 我取票了: 17
[Thread-1] 我取票了: 16
[Thread-1] ==========我取走了: 15
[Thread-2] ==========我取走了: 15
[Thread-0] 我取票了: 15
[Thread-1] 我取票了: 15
[Thread-0] ==========我取走了: 13
[Thread-1] ==========我取走了: 13
[Thread-1] 我取票了: 13
[Thread-2] 我取票了: 13
[Thread-1] ==========我取走了: 11
[Thread-2] ==========我取走了: 11
[Thread-0] 我取票了: 11
[Thread-1] 我取票了: 11
[Thread-1] ==========我取走了: 9
[Thread-0] ==========我取走了: 9
[Thread-1] 我取票了: 9
[Thread-2] 我取票了: 9
[Thread-1] ==========我取走了: 7
[Thread-2] ==========我取走了: 7
[Thread-0] 我取票了: 7
[Thread-2] 我取票了: 7
[Thread-2] ==========我取走了: 5
[Thread-0] ==========我取走了: 5
[Thread-2] 我取票了: 5
[Thread-1] 我取票了: 5
[Thread-2] ==========我取走了: 3
[Thread-1] ==========我取走了: 3
[Thread-2] 我取票了: 3
[Thread-0] 我取票了: 2
[Thread-2] ==========我取走了: 1
[Thread-0] ==========我取走了: 1
[Thread-2] 我取票了: 1
[Thread-1] 我取票了: 1
[Thread-2] ==========我取走了: -1
[Thread-1] ==========我取走了: -1
上面输出结果中,两个线程同时进来取票,最后出现负数,貌似是可以说明Integer不支持线程同步的,
因为 tickets-- 等同于tickets = new Integer(tickets-1),tickets早已不是原来的那个tickets。所以方法2是行不通的。
但是,如果存放“票”的是List却是完全可以的!
博主刚开始学线程,有误之处,欢迎指正!~