线程的控制
休眠线程
public class ThreadSleep extends Thread {
@Override publicvoid run() {
for ( int x = 0; x < 100; x++) {
System. out .println(getName() + ":" + x + ", 日 期 : " + newDate());
// 睡眠
// 困了,我稍微休息 1 秒钟try {
Thread. sleep (1000);
} catch (InterruptedException e)
{ e.printStackTrace();
}
}
}
}
加入线程
publicclass ThreadJoin extends Thread {
@Override publicvoid run() {
for ( int x = 0; x < 100; x++) {
System. out .println(getName() + ":" + x);
}
}
}
ThreadJoin tj1 = new ThreadJoin();
ThreadJoin tj2 = new ThreadJoin();
ThreadJoin tj3 = new ThreadJoin();
tj1.setName(" 李渊 " );
tj2.setName(" 李世民 " );
tj3.setName(" 李元霸 " );
tj1.start(); try {
// 李渊执行完,再执行其他两个
tj1.join();
} catch (InterruptedException e) { e.printStackTrace();
}
tj2.start();
tj3.start();
礼让线程
publicclass ThreadYield extends Thread {
@Override publicvoid run() {
for (int x = 0; x < 100; x++) {
System. out .println(getName() + ":" + x);
// 让其他线程先走
Thread. yield ();
}
}
}
后台线程
ThreadDaemon td1 = new ThreadDaemon();
ThreadDaemon td2 = new ThreadDaemon();
td1.setName(" 关羽 " );
td2.setName(" 张飞 " );
// 设置守护线程,主线程结束后,守护线程也会结束
td1.setDaemon(true); td2.setDaemon(true);
td1.start();
td2.start();
// 设 置 主 线 程 名 为 “ 刘 备 ”
Thread.currentThread().setName(" 刘备 " );
for ( int x = 0; x < 5; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
终止线程
public class ThreadStop extends Thread {
@Override
public void run() {
System. out.println(" 开始执行: " +new Date());
// 我要休息 10 秒钟,亲,不要打扰我哦
try {
Thread.sleep(10000);
}catch(Interrupted Exception e) {
// e.printStackTrace();
System.out.println( " 线程被终止了" );
}
System. out .println(" 结束执行: " +new Date());
}
}
ThreadStop ts =new ThreadStop();
ts.start();
// 你超过三秒不醒过来,我就干死你
try { Thread.sleep(3000);
// ts.stop(); ts.interrupt();
} catch (InterruptedException e)
{
e.printStackTrace();
}
线程的生命周期
多线程安全问题
判断一个程序是否有线程安全问题的依据 )
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
同步解决线程安全问题
同步代码块
synchronized( 对象 ) {
需要被同步的代码 ;
}
这里的锁对象可以是任意对象。
synchronized(d) { if(tickets > 0) {
try { Thread.sleep(100);
} catch (InterruptedException e) { e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ " 正在出售第 " + (tickets--) + " 张 票 " );
}
}
同步方法
把同步加在方法上。这里的锁对象是 this
privatesynchronizedvoid sellTicket() { if(tickets > 0) {
try {
Thread.sleep(100);
} catch(InterruptedException e)
{ e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+" 正在出售第 " + (tickets--) + " 张 票 " );
}
}
静态同步方法
把同步加在方法上。
这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象) private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ " 正在出售第 " + (tickets--) +" 张票 " );
}
}
同步锁对象
// 定义票
private int tickets = 100;
// 定义锁对象
private Lock lock =new ReentrantLock();
@Override
public void run() {
while (true) {
try{
// 加锁
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ " 正在出售第 " + (tickets--) +" 张票 " );
}
}finally{
// 释放锁
lock.unlock();
}
}
}
同步的好处
同步的出现解决了多线程的安全问题。
同步的弊端
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的, 无形中会降低程序的运行效率。