您的位置:首页 > 编程语言 > Java开发

Java线程总结(一)

2016-12-03 11:26 176 查看

一:线程的状态和生命周期

一张经典的描述java线程的图片



线程的基本状态

新建状态: 即新建线程对象 Thread t = new Thread();

就绪状态: 当调用线程的start()方法时,线程进入就绪状态,等待CPU的调度执行。

运行状态: 当CPU开始调用处于就绪状态的线程时,此线程开始执行,进入运行状态。

阻塞状态: 处于运行状态的线程处于某种原因,放弃对CPU的使用权,停止执行,进入阻塞状态,直到该线程再次进入就绪状态,被CPU调用,进入运行状态。进入阻塞状态的原因包括线程等待,线程同步,或IO请求等

死亡状态: 线程执行完成或异常退出run()方法,该线程生命周期结束。

二:java线程的创建

1.实现Runnable接口

class MyRunnable implements Runnable {
private int i = 0;

@Override
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}

public class ThreadTest
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
Thread thread2 = new Thread(myRunnable);
thread1.start(); // 调用start()方法使得线程进入就绪状态
thread2.start();
}
}
}
}


2.继承Thread方法

class MyThread extends Thread {
private int i = 0;

@Override
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}

public class ThreadTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
Thread myThread1 = new MyThread();     // 创建一个新的线程 myThread1 此线程进入新建状态
Thread myThread2 = new MyThread();     // 创建一个新的线程 myThread2 此线程进入新建状态
myThread1.start();                     // 调用start()方法使得线程进入就绪状态
myThread2.start();                     // 调用start()方法使得线程进入就绪状态
}
}
}
}


二:使用Executor

Executors方法是Executor的一个工厂类,里面包含了创建线程池等基本方法

public static ExecutorService newCachedThreadPool();
public static ExecutorService newFixedThreadPool(int nThreads);
public static ExecutorService newSingleThreadExecutor()


1.使用newCachedThreadPool()创建线程

public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new MyThread(i));
exec.shutdown();
}
}


2.使用newFixedThreadPool(int nThreads)创建线程

public class FixedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++)
exec.execute(new MyThread(i));
exec.shutdown();
}
}


3.使用SingleThreadExecutor()创建线程

public class SingleThreadExecutor {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++)
exec.execute(new MyThread(i));
exec.shutdown();
}
}


三:从任务中产生返回值

Callable接口可以在完成任务时产生一个返回值,他是一种具有 类型参数的泛型,他的类型参数表示的是从call()方法中返回的值,并且必须使用ExecutorService.submit()方法调用它。

public class CallableAndFuture {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<Integer> future = threadPool.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
});
try {
Thread.sleep(5000);// 可能做一些事情
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}


调用get()方法以获取当前线程的返回值,可以调用isDone()方法来检查当前线程的任务是否完成

四:休眠

sleep —— 让当前的正在执行的线程暂停指定的时间,并进入阻塞状态。在其睡眠的时间段内,该线程由于不是处于就绪状态,因此不会得到执行的机会。即使此时系统中没有任何其他可执行的线程,出于sleep()中的线程也不会执行。因此sleep()方法常用来暂停线程执行。

public class ThreadTest {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);

for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
thread.start();
try {
Thread.sleep(1);   // 使得thread必然能够马上得以执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

class MyRunnable implements Runnable {

@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}


五:优先级

优先级可以使用setPriority()和getPriority()方法来获取和设置

在调整优先级的时候尽量使用MAX_PRIORITY,MIN_PRIORITY,NORM_PRIORITY三个常量来获取可移植性

public class ThreadTest {

public static void main(String[] args) {
Thread myThread = new MyThread();
for (int i = 0; i < 100; i++) {
System.out.println("main thread i = " + i);
if (i == 20) {
myThread.setPriority(Thread.MAX_PRIORITY);
myThread.start();
}
}
}

}

class MyThread extends Thread {

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
}
}


六:让步

通过调用yeild()方法来将CPU让给别的线程,不过这只是一个建议,没有任何机制保证他会被采纳

public class ThreadTest {

public static void main(String[] args) {
Thread myThread1 = new MyThread1();
Thread myThread2 = new MyThread2();
myThread1.setPriority(Thread.MAX_PRIORITY);
myThread2.setPriority(Thread.MIN_PRIORITY);
for (int i = 0; i < 100; i++) {
System.out.println("main thread i = " + i);
if (i == 20) {
myThread1.start();
myThread2.start();
Thread.yield();
}
}
}

}

class MyThread1 extends Thread {

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("myThread 1 --  i = " + i);
}
}
}

class MyThread2 extends Thread {

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("myThread 2 --  i = " + i);
}
}
}


七:后台线程

概念/目的:后台线程主要是为其他线程(相对可以称之为前台线程)提供服务,或“守护线程”。如JVM中的垃圾回收线程。

生命周期:后台线程的生命周期与前台线程生命周期有一定关联。主要体现在:当所有的前台线程都进入死亡状态时,后台线程会自动死亡。

设置后台线程:调用Thread对象的setDaemon(true)方法可以将指定的线程设置为后台线程。

public class ThreadTest {

public static void main(String[] args) {
Thread myThread = new MyThread();
for (int i = 0; i < 100; i++) {
System.out.println("main thread i = " + i);
if (i == 20) {
myThread.setDaemon(true);
myThread.start();
}
}
}

}

class MyThread extends Thread {

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


也可以使用线程工程来统一指定线程的属性,来创建后台线程

八:join

一个线程可以在其他线程上调用join方法,其效果是等待其他线程结束后在继续执行该线程

public class ThreadTest {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);

for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
thread.start();
try {
thread.join();    // main线程需要等待thread线程执行完后才能继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

class MyRunnable implements Runnable {

@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 线程 Executors