线程相关
线程的3种方式
java1.5 以后java.util.concurrent包, 在并发编程中很常用的实用工具类。
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println("implements Runable...");
}
}
class MyThread extends Thread{s
@Override
public void run() {
System.out.println("extends Thread...");
}
}
class MyThread3 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("implements callable...");
return 200;
}
}
public class ThreadDemo {
public static void main(String[] args) {
new MyThread().start();
new Thread(new MyThread2()).start();
FutureTask task = new FutureTask<>(new MyThread3());
new Thread(task).start();
}
}
//输出
extends Thread...
implements Runable...
implements callable...
线程的小题目
题目:现在两个线程,可以操作同一个变量,实现一个线程对该变量加1,一个线程对该变量减1, 实现交替,来5轮,变量初始值为零。
/**
* 线程实现:现在两个线程,可以操作同一个变量,实现一个线程对该变量加1,一个线程对该变量减1,
* 实现交替,来5轮,变量初始值为零
*
* @author dudy
*/
class ShareData {
private int count = 0;
public synchronized void increment() throws Exception {
while (this.count != 0) {
this.wait();
}
++count;
System.out.println(Thread.currentThread().getName() + "--> " + count);
this.notify();
}
public synchronized void decrement() throws Exception {
while (this.count == 0) {
this.wait();
}
--count;
System.out.println(Thread.currentThread().getName() + "--> " + count);
this.notify();
}
}
public class ThreadDemo02 {
public static void main(String[] args) {
final ShareData data = new ShareData();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "AA").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "BB").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
data.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "CC").start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(500);
data.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "DD").start();
}
}
注意: 当我们在判断等待条件的时候要用while 在 API中 wait()这样写道: 在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
synchronized代码块锁
class Phone
{
public static synchronized void getIOS() throws InterruptedException
{
Thread.sleep(5000);
System.out.println("------getIOS");
}
public synchronized void getAndroid() throws InterruptedException
{
System.out.println("------getAndroid");
}
public void helloPhone() throws InterruptedException
{
System.out.println("------helloPhone");
}
}
public class ThreadDemo3
{
public static void main(String[] args)
{
final Phone phone = new Phone();
final Phone phone2 = new Phone();
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
phone.getIOS();
} catch (InterruptedException e){
e.printStackTrace();
}
}
},"AA").start();
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
//phone.getAndroid();
//phone.helloPhone();
phone2.getAndroid();
} catch (InterruptedException e){
e.printStackTrace();
}
}
},"BB").start();
}
}
//1 首次执行,苹果还是android?
//2 新增Thread.sleep试试,苹果还是android?
//3 新增普通方法试试,苹果还是hello?
//4 新增第2部手机试试,苹果还是android?
//5 换成静态同步方法,同一部手机,苹果还是android?
//6 换成静态同步方法,2部手机,苹果还是android?
//7 一个静态同步方法,另一个非静态同步方法,同一部手机,苹果还是android?
//8 一个静态同步方法,另一个非静态同步方法,2部手机,苹果还是android?
note:
- 一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其他的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法
- 锁的是当前对象this,被锁定后,其他的线程都不能进入到当前对象的其他synchronized方法
- 加个普通方法后发现和同步锁无关
- 换成两个对象后,不是同一把锁了,情况立刻变化
- 都换成静态同步方法后,情况又变化
- 所有的非静态同步方法用的都是同一把锁--实例对象本身
- 所有的静态同步方法用的也是同一把锁--类对象本身