- 前言
- 线程的生命周期
- 线程的创建
- 继承Thread类
- 实现Runnable接口
- Thread 和 Runnable 的区别
线程是 *** 作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成该任务只需10毫秒。为了更好的理解线程知识我特地做了一下分享
线程的生命周期生命周期的五种状态
- 新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。 例如:Thread t1=new Thread();
- 就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
- 运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
- 堵塞(blocked)
(1)等待阻塞 ( o.wait-> 等待对列 )
运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue) 中。
(2)同步阻塞 (lock-> 锁池 )
运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线 程放入锁池(lock pool)中。
(3)其他阻塞 (sleep/join)
运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,
JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O
处理完毕时,线程重新转入可运行(runnable)状态。
- 死亡(dead)
线程会以下面三种方式结束,结束后就是死亡状态。
线程的创建 继承Thread类(1)正常结束: run()或call()方法执行完成,线程正常结束。
(2)异常结束: 线程抛出一个未捕获的Exception或Error。 调用
(3)stop: 直接调用该线程的stop()方法来结束该线程— 该方法通常容易导致死锁,不推荐使用。
- Thread类是所有线程类的父类,实现了对线程的抽取和封装
具体实现见代码如下
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
// 计时器
Long start = System.currentTimeMillis();
Random random = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
// 1、 造一个线程
Thread thread = new Thread() {
@Override
public void run() {
list.add(random.nextInt());
}
};
// 启动线程
thread.start();
// 其目的是等待当前线程执行完毕后,”计算单元”与主线程汇合。即主线程与子线程汇合之意。
/*main是主线程,在main中创建了thread线程,在main中调用了thread.join(),那么等thread结束后再执行main代码。
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,
主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,
需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
“等待该线程终止。”
*/
thread.join();
}
System.out.println("时间" + (System.currentTimeMillis() - start));
System.out.println("大小" + list.size());
}
}
多线程实现卖票
// 创建线程 extends Thread
class Station extends Thread {
// 通过构造方法给线程名字赋值
public Station(String name) {
super(name);// 给线程名字赋值
}
// 为了保持票数的一致,票数要静态
static int tick = 20;
// 创建一个静态钥匙
static Object ob = "aa";//值是任意的
// 重写run方法,实现买票 *** 作
@Override
public void run() {
while (tick > 0) {
synchronized (ob) {// 这个很重要,必须使用一个锁,
// 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来
if (tick > 0) {
System.out.println(getName() + "卖出了第" + tick + "张票");
tick--;
} else {
System.out.println("票卖完了");
}
}
try {
sleep(1000);//休息一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 创建调用方法
class MainClass {
/**
* java多线程同步锁的使用
* 示例:三个售票窗口同时出售10张票
*/
public static void main(String[] args) {
//实例化站台对象,并为每一个站台取名字
Station station1 = new Station("窗口1");
Station station2 = new Station("窗口2");
Station station3 = new Station("窗口3");
// 让每一个站台对象各自开始工作
station1.start();
station2.start();
station3.start();
}
}
-
join是什么
其目的是等待当前线程执行完毕后,”计算单元”与主线程汇合。即主线程与子线程汇合之意。 main是主线程,在main中创建了thread线程,在main中调用了thread.join(),那么等thread结束后再执行main代码。 在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算, 主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后, 需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。 “等待该线程终止。”
代码实现如下到
多线程卖票
// 创建线程
class Runnable1 {
// 为了保持票数的一致,票数要静态
static int tick = 20;
// 创建一个静态钥匙
static Object ob = "aa";//值是任意的
static Runnable runnable = new Runnable() {
@Override
public void run() {
while (tick > 0) {
synchronized (ob) {// 这个很重要,必须使用一个锁,
// 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来
if (tick > 0) {
System.out.println(tick-- + "卖出了第" + tick + "张票");
tick--;
} else {
System.out.println("票卖完了");
}
}
try {
sleep(1000);//休息一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
public static void main(String[] args) {
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
t1.start();
t2.start();
t3.start();
}
}
Thread 和 Runnable 的区别
Thread和Runnable的实质是继承关系,没有可比性。无论使用Runnable还是Thread,都会new Thread,然后执行run方法。用法上,如果有复杂的线程 *** 作需求,那就选择继承Thread,如果只是简单的执行一个任务,那就实现runnable。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)