`

黑马程序员-线程总结

阅读更多

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------

 1、为什么需要线程

     线程给程序提供了不同的执行入口,也使得不同的程序可以同时在内存中运行,而不是一定要等一段代码执行完毕之后再执行下一段。这就是为什么需要线程。

2、线程的创建方式;

    一种是继承Thread类,另一种是实现Runnable接口,一般使用第二种,因为java只支持单继承,而接口可以实现多个,这就使得类的功能更齐全。第二种创建方式基本都是如下:

                      new Thread(new XXClass).start(); (XXClass实现了Runnable接口)

3、线程使用中需要注意的问题:

        a、同步

            当两个线程或两个以上对同一资源进行操作时,就需要对线程进行同步,同步所用的锁必须是同一对象,否则会出现各种乱七八糟的问题,另外同步的代码块或者方法中尽量避免有无需同步的部分。

        b、通信

            当两个或两个以上线程对统一资源进行不同的操作,而这两种操作还有对立性,比方说一个做面包,一个吃面包,那就得有个机制来判断面包有没有的吃,吃没吃完了。这时候用的就是等待与唤醒机制,有三个方法用在此处:

          wai(),  notify(), notifyAll()

        这些方法都是由锁对象调用,wai() 的作用是让当前持有锁的线程等待,notify()随机唤醒一个在锁的范围里等待的线程,notifyAll()则是唤醒所有;这里面要注意一点就是当有三个线程以上时,判断需不需要等待要用while()语句,唤醒都用notifyAll(),否则会出问题,比如线程全部等待(与死锁现象差不多),还有就是连着做同一个动作。

        在JDK1.5以后Lock类使线程的操作更为明朗,更好理解,而且在Lock中可以定义不同的condition来控制线程的唤醒与等待,使其更有目标性,节省内存资源。

       c、其他方法

             join()  执行该方法语句所在的线程会等待调用该方法的对象线程结束,再与其他线程抢资源运行

            interrupt() 将处于冻结状态的线程强制叫醒;被叫醒的线程会抛出一个InterrptedException 异常

            setDaemon()将线程设置为守护线程,守护线程除了人为结束之外,会在该线程所在的线程组中所有的非守护线程都结束之后结束。

            yield() 这个方法用的很少,就是使当前线程暂停一会,然后执行其他线程;就好像是跑累了坐下来休息一会,让别人跑过去就是了

 

下面这个代码完全理解了线程就差不多就可以拿来用了

       

package com.itheima;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 仓库类
 * @author Administrator
 *
 */
class Resource_1 {
	private String name;
	private int count = 1;
	private boolean flag = false;//这个标记用来判断线程等待与否
	private Lock lock = new ReentrantLock();//定义锁
	private Condition con = lock.newCondition();//定义一个condition来控制唤醒与等待
	
	/**
	 * 这个方法是制造仓库中的事物
	 * @param name
	 */
	public void set(String name) {
		lock.lock();//锁上,锁关联的别的线程都稍等
		try {
			while (flag)//用while循环来判断线程是否等待
				con.await();//线程等待
			this.name = name + "--" + count++;
			System.out.println(Thread.currentThread().getName() + "。。生产者。。"
					+ this.name);
			flag = true;//设置属性完毕后改变标签状态
			con.signalAll();//叫醒锁关联的所有在等待的线程
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();//解锁,锁关联的其他线程有机会抢锁了
		}
	}
	
	/**
	 * 这个方法用来消费仓库中的事物
	 * 代码参照制造部分
	 */
	public void show() {
		lock.lock();
		try {
			while (!flag)
				con.await();
			System.out.println(Thread.currentThread().getName()
					+ "。。consumer。。" + this.name);
			flag = false;
			con.signalAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}

	}
}

/**
 * 这个类就是调用仓库中制造事物方法的线程类了
 * @author Administrator
 *
 */
class Producer_2 implements Runnable {
	private Resource_1 res;//定义仓库,确定操作的目标
	
	/**
	 * 在创建实例对象的同时将仓库地址传进来
	 * @param res
	 */
	public Producer_2(Resource_1 res) {
		this.res = res;
	}
	
	/**
	 * 开始制造事物了
	 */
	public void run() {
		while (true) {
			res.set("商品");
		}
	}
}

/**
 * 消费线程
 * @author Administrator
 *
 */
class Consumer_2 implements Runnable {
	private Resource_1 res;

	public Consumer_2(Resource_1 res) {
		this.res = res;
	}

	public void run() {
		while (true) {
			res.show();
		}
	}
}

/**
 * 主线程
 * @author Administrator
 *
 */
public class ProducerConsumer_2 {
	public static void main(String[] args) {
		Resource_1 res = new Resource_1();//建立仓库

		new Thread(new Producer_2(res)).start();
		new Thread(new Consumer_2(res)).start();
		new Thread(new Consumer_2(res)).start();
		new Thread(new Producer_2(res)).start();
	}

}

 

 

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics