java 线程(二)

 线程:
       程序:
       进程:正在内存中运行的程序
       线程:进程中并发运行的的独立过程,是可以单独执行的过程。
     java将操作系统复杂的线程机制封装到了Thread类。
        java如何开启线程:
          1 继承Thread
        2 重写run提供独立运行的过程
          3 创建线程对象
          4 调用Thread提供start方法,将run提交给操作系统,由操作系统调度并执行
         5 操作系统独立的执行run方法
   当前线程:
      是被并发调用的,获取正在执行当前方法的线程,可以使用Thread.crrentThread()     
  
 java启动以后启动主线程,主线程执行了main方法,在main方法中,执行的一系列方法都是被主线程调用的方法。
    使用Runnable接口创建线程
Runnable中有方法run,就是线程中执行的任务方法
    1 实现Runnable接口中的run方法
    2 创建Thread对象,以Runnable接口对象作为参数(提供run方法)
    注:使用Runnable创建线程:线程的执行方法与线程对象分离了,使用更加方便灵活
后台线程:
    java 进程结束条件:当全部的前台线程都结束时候,java进程结束
    如果有没有结束的后台线程,这些线程被提前结束。   
    垃圾回收器,就是利用后台线程进行垃圾回收的

  获取垃圾回收器线程的方法:
	/**
	 * 不建议重写finalize()方法,但是为了获取执行该方法的线程,所以任性一下
	 * 1 是java在回收对象内存空间时候调用的方法
	 * 2 被垃圾回收器调用的方法
	 * 3如果重写必须使用super.finalize();调用Object的
	 * finalize()方法
	 * 	 */
	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		Thread t=Thread.currentThread();
		System.out.println(t.getId()+"  "+t.getName());
		System.out.println(t.getPriority());
		//显示这个对象的类型
		System.out.println(t.getClass().getName());
	}

线程的协调工作:
    1  是可以使用sleep协调两个线程直接的等待关系
    2  使用join连接两个线程:一个线程等待另外一个线程结束再执行(等待的线程被打断时会抛出InterruptedException)
    final  声明的变量被初始化一次不能再改变了
    final  声明的引用变量的指向不能改了,但是所指的对象中的内容是可以改变的。
    在JDK1.8之前 在内部类中使用局部变量,需要将局部变量声明为final类型
IO阻塞方法:read readInt  readLine

线程并发安全:
    public class Demo13 {

	public static void main(String[] args) {
		final House house = new House();
		house.addToy("Tom");
		house.addToy("Jerry");
		Thread t1 = new Thread() {
			@Override
			public void run() {
				try {
					house.showToys();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
		Thread t2 = new Thread() {
			@Override
			public void run() {
				try {
					sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				house.addToy("Nemo");
			}
		};
		t1.start();
		t2.start();
	}
}

class House {
	List<String> toys = new ArrayList<String>();
	List<String> foods = new ArrayList<String>();

	public House() {
		// TODO Auto-generated constructor stub
	}

	public void addToy(String toy) {
		synchronized (toys) {
			toys.add(toy);
		}

	}

	public void showToys() throws InterruptedException {
		synchronized (toys) {
			for (String t : toys) {
				System.out.println(t + " ");
				Thread.sleep(10);
			}
		}
	}

	public void addFood(String food) {
		synchronized (foods) {
			foods.add(food);
		}
	}

	public void showFoods() throws InterruptedException {
		synchronized (foods) {
			for (String t : foods) {
				System.out.println(t + " ");
				Thread.sleep(10);
			}
		}
	}
}


线程间协作
  1 尽量使用单线程处理
  2 必要时候再使用多线程
  3协作方式 sleep+打断 join
 同步代码块 wait notify
  经典解决生产者消费者问题,不用了 阻塞队列方式 解决生产者消费者的问题 方便 JAVA 5

 

public class Demo15 {

	public static void main(String[] args) {
		final BlockingQueue<Double> queue = new LinkedBlockingQueue<Double>(1);
		DemoFrame frame = new DemoFrame();
		frame.setVisible(true);
		// Thread t=new Thread(frame);
		// t.start();
		for (int i = 0; i < 100; i++) {
			double p = i / 100.0;
			try {
				queue.put(p);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// synchronized (frame) {
			// double p = i / 100.0;
			// frame.setPercent(p);
			// try {
			// Thread.sleep(100);
			// } catch (InterruptedException e) {
			// // TODO Auto-generated catch block
			// e.printStackTrace();
			// }
			// }
		}
		frame.setVisible(false);
		System.exit(0);
	}
}

class DemoFrame extends JFrame implements Runnable {

	private JProgressBar bar;
	private JPanel panel;
	private double percent;

	public DemoFrame() {
		bar = new JProgressBar();
		panel = new JPanel(new BorderLayout());
		panel.add(BorderLayout.SOUTH, bar);
		this.add(panel);
		this.setSize(400, 300);
		this.setLocationRelativeTo(null);
		this.setUndecorated(true);
		this.setAlwaysOnTop(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public void setVisible(boolean b) {
		super.setVisible(b);
		if (b) {
			Thread t = new Thread(this);
			t.start();
		}
	}

	public void setPercent(double percent) {
		this.percent = percent;
	}

	@Override
	public void run() {
		while (isVisible()) {

		}
		// while (isVisible()) {
		// synchronized (this) {
		// int n = (int) (percent * 100);
		// bar.setValue(n);
		// this.notify();
		// try {
		// this.wait(2000);
		// } catch (InterruptedException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		// }
		// }
	}

}


 缓冲队列
    阻塞队列
   
    添加数据的方法   
        1  add(数据) 添加成功返回true,如果满添加失败抛出异常
        2  offer(数据) 添加成功返回true, 如果满了添加失败返回false
        3  put(数据)    如果没满直接插入,如果满了就阻塞,直到添加成功为止
        4  offer(数据,等待时间,时间单位) 如果没满直接插入,如果满了就等待指定时间,
         超时还没有添加成功,就返回false,等待期间插入成功返回true;
        3与4被中断是抛出中断异常
    获取数据的方法
        1   remove() 成功就取出数据,队列空抛异常
        2   poll() 成功就取出数据,队列空返回null
        3   take() 成功就取出数据,队列空阻塞到有数据位置
        4   poll(等待时间,时间单位)成功就取出数据,队列空就阻塞,在阻塞
           期间取到数据就返回数据,否则等待时间到也没有得到数据就返回null
          
   检查数据方法(不取出数据) 
         peek() 缓冲队列
    阻塞队列
   
    添加数据的方法   
        1  add(数据) 添加成功返回true,如果满添加失败抛出异常
        2  offer(数据) 添加成功返回true, 如果满了添加失败返回false
        3  put(数据)    如果没满直接插入,如果满了就阻塞,直到添加成功为止
        4  offer(数据,等待时间,时间单位) 如果没满直接插入,如果满了就等待指定时间,
         超时还没有添加成功,就返回false,等待期间插入成功返回true;
        3与4被中断是抛出中断异常
    获取数据的方法
        1   remove() 成功就取出数据,队列空抛异常
        2   poll() 成功就取出数据,队列空返回null
        3   take() 成功就取出数据,队列空阻塞到有数据位置
        4   poll(等待时间,时间单位)成功就取出数据,队列空就阻塞,在阻塞
           期间取到数据就返回数据,否则等待时间到也没有得到数据就返回null
          
   检查数据方法(不取出数据) 
         peek() 缓冲队列
    阻塞队列
   
    添加数据的方法   
        1  add(数据) 添加成功返回true,如果满添加失败抛出异常
        2  offer(数据) 添加成功返回true, 如果满了添加失败返回false
        3  put(数据)    如果没满直接插入,如果满了就阻塞,直到添加成功为止
        4  offer(数据,等待时间,时间单位) 如果没满直接插入,如果满了就等待指定时间,
         超时还没有添加成功,就返回false,等待期间插入成功返回true;
        3与4被中断是抛出中断异常
    获取数据的方法
        1   remove() 成功就取出数据,队列空抛异常
        2   poll() 成功就取出数据,队列空返回null
        3   take() 成功就取出数据,队列空阻塞到有数据位置
        4   poll(等待时间,时间单位)成功就取出数据,队列空就阻塞,在阻塞
           期间取到数据就返回数据,否则等待时间到也没有得到数据就返回null
          
   检查数据方法(不取出数据) 
         peek() 缓冲队列
    阻塞队列
   
    添加数据的方法   
        1  add(数据) 添加成功返回true,如果满添加失败抛出异常
        2  offer(数据) 添加成功返回true, 如果满了添加失败返回false
        3  put(数据)    如果没满直接插入,如果满了就阻塞,直到添加成功为止
        4  offer(数据,等待时间,时间单位) 如果没满直接插入,如果满了就等待指定时间,
         超时还没有添加成功,就返回false,等待期间插入成功返回true;
        3与4被中断是抛出中断异常
    获取数据的方法
        1   remove() 成功就取出数据,队列空抛异常
        2   poll() 成功就取出数据,队列空返回null
        3   take() 成功就取出数据,队列空阻塞到有数据位置
        4   poll(等待时间,时间单位)成功就取出数据,队列空就阻塞,在阻塞
           期间取到数据就返回数据,否则等待时间到也没有得到数据就返回null
          
   检查数据方法(不取出数据) 
         peek() 缓冲队列
    阻塞队列
   
    添加数据的方法   
        1  add(数据) 添加成功返回true,如果满添加失败抛出异常
        2  offer(数据) 添加成功返回true, 如果满了添加失败返回false
        3  put(数据)    如果没满直接插入,如果满了就阻塞,直到添加成功为止
        4  offer(数据,等待时间,时间单位) 如果没满直接插入,如果满了就等待指定时间,
         超时还没有添加成功,就返回false,等待期间插入成功返回true;
        3与4被中断是抛出中断异常
    获取数据的方法
        1   remove() 成功就取出数据,队列空抛异常
        2   poll() 成功就取出数据,队列空返回null
        3   take() 成功就取出数据,队列空阻塞到有数据位置
        4   poll(等待时间,时间单位)成功就取出数据,队列空就阻塞,在阻塞
           期间取到数据就返回数据,否则等待时间到也没有得到数据就返回null
          
   检查数据方法(不取出数据) 
         peek()

 

public class Demo01 {
	public static void main(String[] args) {
		final BlockingQueue<String> queue = new LinkedBlockingQueue<String>(3);
		// queue.add("Tom");
		// queue.add("Jerry");
		// queue.add("Nemo");
		Thread t1 = new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
					System.out.println("插入前" + queue);
					System.out.println("开始插入数据");
					queue.put("John");
					System.out.println("插入后" + queue);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		Thread t2 = new Thread() {
			@Override
			public void run() {
				try {
					System.out.println("开始取出数据");
					String name = queue.take();
					System.out.println("取出了:" + name);
					System.out.println("取出了" + queue);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		};
		t1.start();
		t2.start();
	}
} 


 

/**
 * 线程池
 * 
 * ExecutorService执行器服务 Executors 工厂
 * 
 * @author tarena
 *
 */
public class Demo03 {
	// @Test
	public void test() throws InterruptedException {
		// 尽量重用已经存在的线程,如果不存在就创建新的
		// 但是旧线程使用以后,还会加以重用
		// ExecutorService p1=Executors.newCachedThreadPool();
		// 创建两个任务(两个run方法),先提交一个任务,当一个任务结束以后,我再提交第二个任务
		// 先后提交任务使用了同一个线程,执行的!
		// execute将一个任务提交到线程池,由线程池派发线程池执行
		// p1.execute(new Task());
		// Thread.sleep(1000);
		// p1.execute(new Task());

	}

	// @Test
	public void testNewFixedThreadPool() {
		/*
		 * 最多重用3个线程,执行任务,更多任务将等到执行
		 */
		ExecutorService p2 = Executors.newFixedThreadPool(3);
		for (int i = 0; i < 10; i++) {
			p2.execute(new Task());
		}
	}

//	@Test
	public void testSingleThread() {
		/**
		 * 只重用一个线程,执行任务,更多代码将等待
		 */
		ExecutorService pool=Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			pool.execute(new Task());
		}
	}
	@Test
	public void test1() throws InterruptedException{
		/**
		 * 利用重用的线程,定时执行计划任务,控制线程总数
		 */
		ScheduledExecutorService pool=
				Executors.newScheduledThreadPool(4);
		//一次性执行任务
		pool.schedule(new Task(), 2,TimeUnit.SECONDS);
		//定期执行任务
		pool.scheduleAtFixedRate(new Task(), 0,1,TimeUnit.SECONDS);
		Thread.sleep(10000);
				
	}

}

class Task implements Runnable {
	@Override
	public void run() {
		Thread t = Thread.currentThread();
		System.out.println(t.getName() + "," + t.getId());
	}
}

 

/**
 * ThreadLocal
 *  属于线程的变量
 *  
 * 局部变量:在方法中声明,离开作用域就销毁的变量,在栈中分配。局部变量也是临时变量。
 *     每个线程都有一个栈。(每个线程都有自己的栈)
 * 实例变量:对象属性,是属于对象的变量,在堆中分配,多个线程都可以共享同一个对象。  
 * 属于线程的变量:ThreadLocal,是存储在线程上的变量。可以利用这个变量,
 *   在同一个线程调用一系列方法时共享数据。这些数据存储在线程对象中的一个Map集合(每一个线程都会维护一个Map集合)中。
 * @author tarena
 *
 */

public class Demo06 {

	public static void main(String[] args) {
		final Shop  shop=new Shop();
		final int s=0;
		Thread p1=new Thread(){
			@Override
			public void run() {
				try {
					int e=s;
					Account.setName("Tom");
					shop.getMoney();
					Thread.sleep(1000);
					shop.getProduct();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		Thread p2=new Thread(){

			@Override
			public void run() {
				try {
					Account.setName("Jerry");
					shop.getMoney();
					Thread.sleep(1000);
					shop.getProduct();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		
		};
		p1.start();
		p2.start();
	}
}


class Account{
	private static ThreadLocal<String> name=new ThreadLocal<String>(){
		protected String initialValue() {
			return "NO Name";
		}
	};
	
	public static synchronized void  setName(String name){
		String n=Account.name.get();
		if(n==null){
			n=name;
			Account.name.set(name);
		}
	}
	public static synchronized String getName(){
		/*
		 * 为了保证创建唯一的一个对象,避免因为并发线程重复创建对象
		 * 经常利用同步关键字,保证代码的原子性,在执行期间不会发生并发访问的问题
		 */
		String n=Account.name.get();
		if(n==null){
			Account.name.set("佚名");
		}
		return n;
	}
}

class Shop{
	public void getMoney(){
		String name=Account.getName();
		Thread t=Thread.currentThread();
		System.out.println("线程"+t.getName()+
				"被用户:"+name+"使用去取钱了");
	}
	public void getProduct(){
		String name=Account.getName();
		Thread t=Thread.currentThread();
		System.out.println("线程"+t.getName()+
				"被用户:"+name+"使用去购物了");
	}
}


 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值