Java 多线程实例 3 种实现方法
Java 中的多线程有三种实现方式:
1. 继承 Thread 类,重写 run 方法。Thread 本质上也是一个实现了 Runnable 的实例,他代表一个线程的实例,并且启动线程的唯一方法就是通过 Thread 类的 start 方法。
2. 实现 Runnable 接口,并实现该接口的 run() 方法. 创建一个 Thread 对象,用实现的 Runnable 接口的对象作为参数实例化 Thread 对象,调用此对象的 start 方法。
3. 实现 Callable 接口,重写 call 方法。Callable 接口与 Runnable 接口的功能类似,但提供了比 Runnable 更强大的功能。有以下三点
1).Callable 可以在人物结束后提供一个返回值,Runnable 没有提供这个功能。
2).Callable 中的 call 方法可以抛出异常,而 Runnable 的 run 方法不能抛出异常。
3). 运行 Callable 可以拿到一个 Future 对象,表示异步计算的结果,提供了检查计算是否完成的方法。
需要注意的是,无论用那种方式实现了多线程,调用 start 方法并不意味着立即执行多线程代码,而是使得线程变为可运行状态。
run start 的区别
start 方法是启动一个线程,而线程中的 run 方法来完成实际的操作。
如果开发人员直接调用 run 方法,那么就会将这个方法当作一个普通函数来调用,并没有多开辟线程,开发人员如果希望多线程异步执行,则需要调用 start 方法。
sleep wait 的区别
1. 两者处理的机制不同,sleep 方法主要是,让线程暂停执行一段时间,时间一到自动恢复,并不会释放所占用的锁,当调用 wait 方法以后,他会释放所占用的对象锁,等待其他线程调用 notify 方法才会再次醒来。
2.sleep 是 Threa 的静态方法,是用来控制线程自身流程的,而 wait 是 object 的方法,用于进行线程通信。
3. 两者使用的区域不同。sleep 可以在任何地方使用,wait 必须放在同步控制方法,或者语句块中执行。
synchronized notify wait 的运用
synchronized 关键字有两种用法,synchronized 方法和 synchronized 语句块。
public synchronized void function(){}
synchronized(object){}
当某个资源被 synchronized 所修饰,线程 1 线程 2 等多个线程在共同请求这个资源,线程 1 先请求到,调用了对象的 wait 方法释放了对象的锁,此时线程 2 可以对这个对象进行访问,在工作结束时可以调用对象的 notify 方法,唤醒等待队列中正在等待的线程,此时被唤醒的线程将会再一次拿到对象锁,对对象进行操作。可以调用 notifyAll 方法,唤醒等待队列中的所有线程。
需要注意的是一个线程被唤醒不代表立即获取对象锁,必须等调用的线程对象的方法推出 synchronized 块释放对象锁后,被唤醒的进程才会获得对象锁。
以下为大家提供一个简单的代码实例:
分别用 Runnable 和 Thread 方法实现,展示各个方法的
实现 Runnable 实现多线程的方法
- public class TestRunnable implements Runnable {
- private int time = 1;
- private SourceA s;
- private String id = "001";
- public TestRunnable(SourceA s) {
- this.s = s;
- }
- public void setTime(int time) {
- this.time = time;
- }
- @Override public void run() {
- try {
- System.out.println("i will sleep" + time);
- Thread.sleep(time);
- } catch(InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- synchronized(s) {
- s.notify();
- System.out.println("我唤醒了002!");
- System.out.println("我存入了id" + id);
- s.setSource(id);
- }
- }
- }
继承 Thread 实现多线程的方法
- public class TestThread extends Thread {
- private int time = 1;
- private SourceA s = null;
- String id = "002";
- public void setTime(int time) {
- this.time = time;
- }
- public TestThread(SourceA s) {
- this.s = s;
- }
- @Override public void run() {
- try {
- System.out.println("i will sleep" + time);
- sleep(time);
- } catch(InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- synchronized(s) {
- try {
- System.out.println("我" + id + "要进行等待了");
- s.wait();
- } catch(InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println("我被唤醒了");
- System.out.println("我存入了id" + id);
- s.setSource(id);
- }
- }
- }
SourceA 类代码:
- public class SourceA {
- private List < String > list = new ArrayList < String > ();
- public synchronized void getSource() {
- for (int i = 0; i < list.size(); i++) {
- System.out.println(list.get(i));
- }
- }
- public synchronized void setSource(String id) {
- list.add(id);
- }
- }
Test 测试类代码:
- public void test() {
- SourceA s = new SourceA();
- TestThread tt = new TestThread(s);
- TestRunnable tr = new TestRunnable(s);
- Thread t = new Thread(tr);
- System.out.println("调用线程1");
- tt.start();
- System.out.println("调用线程2");
- t.start();
- }
结果图片:
来源: http://www.phperz.com/article/17/1219/357679.html