1.如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换. 2.更多的线程需要更多的内存空间 3.线程中止需要考虑对程序运行的影响. 4.通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生 什么时候会用到线程? 当系统中或者开发中。遇到高并发 并行的情况下为了解决负载均衡的问题,就会使用到线程。线程可以提高cpu的利用率。 Thread里面一个特殊的方法run();这个方法就是为执行一个线程而做准备的(当你创建了一个新的线程以后,所有实现的业务逻辑全部在run()方法里面),也就是说在run()方法里面写什么业务。线程就执行实现什么业务。 启动一个线程用start()方法,也就是说当调用Start()方法线程准备就绪以后。才能去启动执行run()方法里面的所有业务逻辑。 Therad线程类提供了好多方法。最常用的有sleep()方法,调用此方法是让一个线程处于睡眠状态。它是Thread类的一个静态方法。sleep()在使用过程中会抛出异常。当在处理异常的时候用try{}catch{}。当重写的方法无法用throws来处理异常时。就必须用try{}catch{}来处理异常。 线程的优先级:setPriority();用此方法就是设置线程的优先级。 修改线程优先级 public final static int MIN_PRIORITY = 1; public final static int NORM_PRIORITY = 5; public final static int MAX_PRIORITY = 10; setPriority的参数在1 - 10 之间就可以, 否则会抛异常
线程调度
计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令。所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得CPU的使用权,分别执行各自的任务。在运行池中,会有多个处于就绪状态的线程在等待CPU,JAVA虚拟机的一项任务就是负责线程的调度,线程调度是指按照特定机制为多个线程分配CPU的使用权。<br />1.分时调度<br />所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。<br />2.抢占式调度<br />优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
Java实现多线程的方式
1、继承Thread类创建线程Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。 public class MyThread extends Thread { public void run() { System.out.println(“MyThread.run()”); } }
MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start(); 2、实现Runnable接口创建线程如果自己的类已经extends另一个类,就无法直接extends Thread,此时,可以实现一个Runnable接口 public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println(“MyThread.run()”); } } 为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例: MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); 3、实现Callable接口通过FutureTask包装器来创建Thread线程 public interface Callable { V call() throws Exception; }
——————————————————————————————————————- public class SomeCallable extends OtherClass implements Callable { @Override public V call() throws Exception { return null; } } ——————————————————————————————————————- Callable oneCallable = new SomeCallable(); //由Callable创建一个FutureTask对象: FutureTask oneTask = new FutureTask(oneCallable); //注释:FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口。 //由FutureTask创建一个Thread对象: Thread oneThread = new Thread(oneTask); oneThread.start(); //至此,一个线程就创建完成了。 4、使用ExecutorService、Callable、Future实现有返回结果的线程 ExecutorService、Callable、Future三个接口实际上都是属于Executor框架。返回结果的线程是在JDK1.5中引入的新特征,有了这种特征就不需要再为了得到返回值而大费周折了。而且自己实现了也可能漏洞百出。 可返回值的任务必须实现Callable接口。类似的,无返回值的任务必须实现Runnable接口。 执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了。 注意:get方法是阻塞的,即:线程无返回结果,get方法会一直等待。 再结合线程池接口ExecutorService就可以实现有返回结果的多线程了。 import java.util.concurrent.; import java.util.Date; import java.util.List; import java.util.ArrayList;
/** 有返回值的线程 */ @SuppressWarnings(“unchecked”) public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(“——程序开始运行——“); Date date1 = new Date();
int taskSize = 5; // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 List list = new ArrayList(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable(i + “ “); // 执行任务并获取Future对象 Future f = pool.submit(c); // System.out.println(“>>>” + f.get().toString()); list.add(f); } // 关闭线程池 pool.shutdown();
// 获取所有并发任务的运行结果 for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println(“>>>” + f.get().toString()); }
Date date2 = new Date(); System.out.println(“——程序结束运行——,程序运行时间【” + (date2.getTime() - date1.getTime()) + “毫秒】”); } }