线程初始化后的状态:可运行/就绪状态、(抢占到CPU)运行状态、(等待)阻塞状态、(运行完毕)死亡状态
实现
实现线程 方式一 (继承)
run()
方法称为 线程体
public class FirstThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (int i = 0; i < 100; i++) {
System.out.println("first thread" + i);
}
}
}
使用
public static void main(String[] args) {
// TODO Auto-generated method stub
FirstThread fThread = new FirstThread();
fThread.start();
for (int i = 0; i < 100; i++) {
System.out.println("main thread ------ " + i);
}
}
运行结果
main thread ------ 0
first thread0
main thread ------ 1
first thread1
main thread ------ 2
first thread2
main thread ------ 3
main thread ------ 4
...
自定义线程 之外,还有主线程、垃圾回收线程。
其中 自定义线程、主线程抢占CPU,交替运行
实现线程 方式二 (实现接口)
public class RunnableImpl implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("impl do sth");
}
}
RunnableImpl ri = new RunnableImpl();
Thread thread = new Thread(ri);
thread.start();
线程控制
- 中断线程
sleep:中断当前线程 [阻塞/休眠状态]
Thread.sleep(2000);//2000ms
那什么时候运行呢?
2000ms后[就绪] + 抢占CPU耗时n后 ->[运行状态]
yield,暂停当前正在执行的线程对象,并让步给其它线程(有机会)执行
Thread.yield();
什么时候运行?
瞬间中断 -> 抢占资源 -> 运行
有这样的结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果(因为让步的线程还有可能被线程调度程序再次选中)。
- 设置优先级
thread.setPriority(Thread.MAX_PRIORITY); thread.setPriority(Thread.MIN_PRIORITY);
默认是5,max:10, min:1
尽管设置了优先级,也并不一定总是优先级高的抢占到CPU,只是概率相对更高一些
多线程数据安全
定义MyThread类,线程体
public class MyThread implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
System.out.println(Thread.currentThread().getName() + i);
i--;
Thread.yield();
if (i < 0) {
break;
}
}
}
}
多个线程、同一个线程体,运行
static void multiThread() {
MyThread m = new MyThread();
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
t1.setName("线程A");
t2.setName("thread B");
t1.start();
t2.start();
}
运行结果
/* ...
* thread B96
thread B95
线程A95
thread B94
线程A93
...
* */
多线程共用同一份资源(数据)时,操作数据时发生 B95->A95 这样的现象。相当于12306卖票时,同一份票被卖给了2个用户。
锁
使用synchronized,可对共享数据加锁保护
while (true) {
//自动释放锁synchronized,用于多线程中对共享数据保护
synchronized (this) {
System.out.println(Thread.currentThread().getName() + i);
i--;
Thread.yield();
if (i < 0) {
break;
}
}
}
不再发生B95->A95
这样数据不安全的现象
若A线程拿到这个锁后,执行锁住的代码块。若A还没执行完,此时若B抢占到CPU,B因为没拿到该锁,所以无法使用锁内代码,直到A释放锁,B才有机会拿到锁,才可以在抢占到CPU后执行锁内代码.
网友评论