创建线程的三种方式以及线程的状态(代码走一遍)

it2025-04-20  2

线程的特点:

1、抢占式线程

效率高可防止单一线程长时间占用cpu

2、在单核cpu中,宏观上同时执行,微观上顺序执行。

线程的状态:

初始状态–就绪状态–运行状态–终止状态 此外还有限期等待(sleep(n))–无限期等待join()–阻塞状态(synchronized) 请看下图: 但是在JDK5之后,就绪状态和运行状态统称Runnable

具体的状态我们可以通过getState()方法看到。

public enum State { /** * Thread state for a thread which has not yet started. * 线程刚创建好之后的初始状态 */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. * 线程的运行状态,或者等待时间片选中的状态为Runnable */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. * 未获得锁的状态 */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. * 调用join方法后其他线程进入waitting状态 */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> * 调用sleep方法后其他线程进入timed_waitting状态 */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. * 线程终止状态 */ TERMINATED; }

创建线程的三种方式:

1、继承Thread类,重写run方法2、实现Runnable接口3、实现Callable接口

1、继承Thread类,重写run方法

public class MyThread extends Thread{ public MyThread() { } public MyThread(String name) { super(name); } @Override public void run() { int i =100; for (int i1 = 0; i1 < i; i1++) { System.out.println("子线程"+i1+" 线程Name: "+ this.getName()+" :线程ID : "+this.getId()); } } public static void main(String[] args) { MyThread myThread = new MyThread("nxw"); myThread.start(); MyThread myThread1 = new MyThread("silence"); myThread1.start(); for (int i=0;i<100;i++){ System.out.println("主线程:"+i); } } }

在MyThread 类中有一个main方法,在执行main方法的时候会开启一个主线程来执行,在执行过程中有开启了子线程来执行myThread. 从以上代码中执行结果会出现主线程的子线程交替打印的情况 但是如果你想先执行myThread,在执行myThread1,最后打印主线程的话,你只需要加上这样一段代码就可以了 myThread.join(); myThread1.join(); 注意这时候就需要抛异常了throws InterruptedException

2、实现Runnable接口

public class MyRunnable implements Runnable { public synchronized void run() { for (int i = 0;i<101;i++){ System.out.println("子线程ID:"+Thread.currentThread().getId()+"子线程Name:"+Thread.currentThread().getName() +"子线程:"+i); } } } class TestMyRunnable{ public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable,"runnable: "); Thread thread1 = new Thread(myRunnable,"runnable1: "); thread.start(); thread1.start(); for (int i = 0;i<101;i++){ System.out.println("主线程:"+i); } } }

3、实现Callable接口

public class TestCallable { public static void main(String[] args) { Callable<Integer> callable = new Callable<Integer>() { public Integer call() throws Exception { int sum = 0; for(int i=0;i<101;i++){ sum += i; } return sum; } }; FutureTask task = new FutureTask(callable); Thread thread = new Thread(task); Thread thread1 = new Thread(); thread.start(); Object o = null; try { o = task.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println(o); //打印结果5050 } }

以上就是实现多线程的三种方式,但是要着重说一下实现Callable这种方式。 根据代码可以看出来,实现Callable后不能直接把对象给Thread对象,而是要经过FutureTask 包装后才能交给Thread。再仔细一点你就会发现实现Callable接口还需要抛出异常。

通过以上代码我们可以总结一下三种创建线程方式的区别:

三种创建线程方式的区别

1、实现线程方式大体可分为两类,一类是继承,一类是接口实现。 2、接口实现可以避免单继承的局限性。 3、Runnable要实现的方法是run()方法,Callable()要实现的方法是call()方法。 4、Callable任务执行完毕后会有返回值,而Runnable是没有返回值的。 5、call()方法需要抛异常,而run()方法不需要抛异常。 6、Callable对象需要交给FutureTask对象包装后才能交给Thread开启线程,而Runnable可以直接交给Thread。 7、Callable执行完毕后可以通过futureTask获取线程执行结果。

最新回复(0)