线程的创建
- 继承Thread类,重写run()方法,然后对线程类进行实例化,调用start()方法就行
- 实现Runnable接口
- 匿名内部类形式来创建线程
常用方法
-
join()方法
当main方法开始执行时,就已经创建了个主线程。当开启了另外的一个线程的时候,此时程序就有了两个线程,它们的执行过程是main线程和新开的线程交替执行。如果想先指向新开的线程,再执行主线程,则可以实例化线程后,调用join()方法即可。 -
stop()方法
强制结束当前线程(已过时) -
sleep()
睡眠,当线程执行到这里的时候,发生阻塞,可以设置阻塞时间,结束后就执行后面的代码
-setPriority()
不设置优先级的话,主线程和分线程都是默认优先级NORM_PRIORITY:5,即是设置了优先级,也只是代表某个线程优先执行,并不是说就一定先执行完在执行另一个线程。只能说优先级比较高的高概率被CPU执行到
比较Thread和Runnable
推荐用Runnable;理由:
- 如果继承Thread的话,就不能继承其他类了
- 更能体现数据的共享性
线程安全案例:卖票问题
- 解决思路
开启多个线程卖票,当一个线程在操作ticket的时候,其他线程不能参与进来,知道此线程操作完过后,才能操作下一个线程。 - 解决方法:
方法一:同步代码块
synchronize(同步监视器){
//需要被同步的代码
}
说明:操作共享数据的代码即是同步的代码
同步监视器:俗称—锁。任何一个类的对象,都可以当成锁
package com.ranqing.thread;
class Window implements Runnable{
private int ticket=10000;
Object obj=new Object();
@Override
public void run() {
while(true) {
synchronized (obj){//锁的要求:多个线程必须要公用同一把锁
if (ticket>0) {
System.out.println(Thread.currentThread().getName()+":卖票,票号为:"+ticket);
ticket--;
}else {
break;
}
}
}
}
}
public class WindowTest {
public static void main(String[] args) {
Window window=new Window();
Thread t1=new Thread(window);
Thread t2=new Thread(window);
Thread t3=new Thread(window);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}