------------Android培训
、Java培训、期待与您交流----------
1.wait()、sleep()、notify()、notifyAll()方法
wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程(一般是最先开始等待的线 程),而且不是按优先级。
notifyAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
为什么wait()、notify()、notifyAll()这些用来操作线程的方法定义在Object类中?
(1)这些方法只存在于同步中;
(2)使用这些方法时必须要指定所属的锁,即被哪个锁调用这些方法;
(3)而锁可以是任意对象,所以任意对象调用的方法就定义在Object中。
class StopThread implements Runnable
{
private boolean flag = true;
public synchronized void run()
{
while(flag)
{
try
{
wait();//线程冻结
}
catch (InterruptedException e)
{
System.out.println(Thread.currentThread().getName()+"...Exception");
flag = false;
}
System.out.println(Thread.currentThread().getName()+"...run");
}
}
/*
public void changeF()
{
flag = false;
}
*/
}
/*
* 主线程是前台线程,主线程一结束,其他线程自动就结束了。
*/
public class ThreadStop
{
public static void main(String[] args)
{
StopThread st= new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.setDaemon(true);//守护线程(必须在启动线程前调用)
t2.setDaemon(true);
t1.start();
t2.start();
int i = 0;
while(true)
{
if(i++ == 60)
{
//st.changeF();
//t1.interrupt();//强制恢复线程
//t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"......"+i);
}
System.out.println(Thread.currentThread().getName()+"...over...");
}
}
2.多个窗口同时卖票问题
创建线程的第二个方法:实现Runnable()接口(最为常用的方法)
步骤:
步骤:
1.定义一个类实现Runnable()接口
2.覆盖Runnable()接口中的run方法将线程要运行的代码放在run方法中
3.通过Thread类建立线程对象
4.将Runnable()接口的子类对象作为实际参数传递给Thread类的构造函数为什么要将Runnable()接口的子类对象传递给Thread类的构造函数?
因为自定义的run方法所属的对象是Runnable()接口的子类对象。所以要让线程去执行指定对象的run方法
5.调用Thread类的start方法开启线程并调用
P.S.实现Runnable()方式和继承方式有什么区别?
前者避免了java单继承的局限性问题,在定义线程时建议使用implements实现方式。
区别:
extends Thread 线程的代码存放在Thread子类的run方法中
implements Runnable 线程代码存放在接口的子类的run方法中
2.覆盖Runnable()接口中的run方法将线程要运行的代码放在run方法中
3.通过Thread类建立线程对象
4.将Runnable()接口的子类对象作为实际参数传递给Thread类的构造函数为什么要将Runnable()接口的子类对象传递给Thread类的构造函数?
因为自定义的run方法所属的对象是Runnable()接口的子类对象。所以要让线程去执行指定对象的run方法
5.调用Thread类的start方法开启线程并调用
P.S.实现Runnable()方式和继承方式有什么区别?
前者避免了java单继承的局限性问题,在定义线程时建议使用implements实现方式。
区别:
extends Thread 线程的代码存放在Thread子类的run方法中
implements Runnable 线程代码存放在接口的子类的run方法中
class TicketThread implements Runnable//extends Thread
{
private /*static第一种方式中实现使用*/ int ticket = 100;
//Object obj = new Object();
public void run()
{
while(true)
{
//synchronized(obj)锁
if(ticket>0)
{
/*通过分析发现结果因此出现负数票结果,导致多线程出现了安全问题
* 原因:当多条语句在操作同一个线程共享数据资源时,一个线程对多条语句
* 只执行了一部分尚未执行完,另一个线程就参与进来,导致共享数据的错误
* 解决法:对多条操作共享数据的线程在某一时间段只能允许一个线程执行,此过程中
* 其他线程不可参与运行。
* java对于多线程的安全问题提供了'同步代码块'
* synchronized(Object obj)
* {
* 需要同步的代码(操作共享数据的语句);
* if(ticket>0)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
// TODO: handle exception对异常未做处理
}
System.out.println(Thread.currentThread().getName()+ " sold..."+ticket-- );
}
}
同步的前提:1.必须要有两个或者两个以上的线程
2.必须是多个线程使用同一个锁
必须保证同步中只有一个线程在运行
弊端:因为每个线程每次都要判断锁的状态,占用并消耗了较多的系统资源,程序运行会比较慢。
*/
/*
try
{
Thread.sleep(10);
}
catch (Exception e)
{
// TODO: handle exception对异常未做处理
}
*/
System.out.println(Thread.currentThread().getName()+ " sold..."+ticket-- );
}
}
}
}
public class TicketSell
{
public static void main(String[] args)
{
TicketThread t = new TicketThread();
Thread t1 = new Thread(t);//指定run方法所属对象t
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();//调用的是Thread中的run方法
t2.start();
t3.start();
t4.start();
}
}
------------Android培训
、Java培训、期待与您交流----------