java--多线程--线程的操作

要操作线程就要知道线程的七种状态:

线程的生命周期包含七种状态:
出生状态,就绪状态,运行状态,等待状态,休眠状态,阻塞状态和死亡状态。


使线程处于就绪状态有以下几种方法:
1.调用sleep()方法。
2.调用wait()方法。
3.等待输入/输出完成。


当线程处于就绪状态后。有一下几种方法进行运行:
1.线程调用notity()方法。
2.线程调用notityAll()方法。
3.线程调用interrupt()方法。
4.线程的休眠时间结束。
5.输入/输出结束。




控制线程:使线程从一种状态过渡到另一种状态。


1.线程的休眠。
控制线程休眠调用sleep()方法,sleep()方法需要一个参数用于指定该线程休眠的时间,
该时间以毫秒为单位,它通常是在run()方法内的循环中被使用。

sleep()方法语法:
try{
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}
这个代码会使线程进入两秒的休眠状态,由于sleep()方法的执行可能抛出InterruptedException异常,所以sleep()方法放入try-catch语句块中。
虽然使用了sleep()方法的线程会自动醒过来,但是醒来后不一定能进入运行状态,只能保证它进入就绪状态。

让线程每过100ms自减一次。

public class Test extends Thread{

	int count=0;
	public void run(){
		while(true){
		try{
			Thread.sleep(100);
		}catch(Exception e){
			e.printStackTrace();
		}
		if(count<100){
	       System.out.println(count++);
		}else{
	        break;
		}
	 }
	}
	public static void main(String[] args){
		Test t = new Test();
		Thread A = new Thread(t);
		
		A.start();
	}
}


创建一个不包含停向右滑动的图片窗口

import java.awt.*;
import java.util.*;

import javax.swing.*;
public class SleepMethodTest extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Thread t;
	// 定义颜色数组
	private static Color[] color = { Color.BLACK, Color.BLUE, Color.CYAN,
			Color.GREEN, Color.ORANGE, Color.YELLOW, Color.RED,
			Color.PINK, Color.LIGHT_GRAY };
	private static final Random rand = new Random();// 创建随机对象
	
	private static Color getC() {// 获取随机颜色值的方法
		return color[rand.nextInt(color.length)];
	}
	
	public SleepMethodTest() {
		t = new Thread(new Runnable() {// 创建匿名线程对象
			int x = 30;// 定义初始坐标
			int y = 50;
			
			public void run() {// 覆盖线程接口方法
				while (true) {// 无限循环
					try {
						Thread.sleep(100);// 线程休眠0.1秒
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					// 获取组件绘图上下文对象
					Graphics graphics = getGraphics();
					graphics.setColor(getC());// 设置绘图颜色
					// 绘制直线并递增垂直坐标
					graphics.drawLine(x, y, 100, y++);
					if (y >= 80) {
						y = 50;
					}
				}
			}
		});
		t.start();// 启动线程
	} 
	
	public static void main(String[] args) {
		init(new SleepMethodTest(), 100, 100);
	}
	// 初始化程序界面的方法
	public static void init(JFrame frame, int width, int height) {
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(width, height);
		frame.setVisible(true);
	}
}



2.线程的加入
控制线程加入调用join()方法,当某个线程使用join()方法加入到另一个线程时,另一个线程会等待该线程执行完毕后再继续执行。
join()也是放入try-catch语句块中。


定义两个进度条,在进度条B执行完成后让进度条A加入。

import java.awt.*;

import javax.swing.*;

public class JoinTest2 extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Thread threadA; // 定义两个线程
	private Thread threadB;
	final JProgressBar progressBar = new JProgressBar(); // 定义两个进度条组件
	final JProgressBar progressBar2 = new JProgressBar();
	int count = 0;
	
	public static void main(String[] args) {
		init(new JoinTest(), 100, 100);
	}
	
	public JoinTest2() {
		super();
		// 将进度条设置在窗体最北面
		getContentPane().add(progressBar, BorderLayout.NORTH);
		// 将进度条设置在窗体最南面
		getContentPane().add(progressBar2, BorderLayout.SOUTH);
		progressBar.setStringPainted(true); // 设置进度条显示数字字符
		progressBar2.setStringPainted(true);
		// 使用匿名内部类形式初始化Thread实例子
		threadA = new Thread(new Runnable() {
			int count = 0;
			
			public void run() { // 重写run()方法
				while (true) {
					progressBar.setValue(++count); // 设置进度条的当前值
					try {
						Thread.sleep(100); // 使线程A休眠100毫秒
						threadB.join(); // 使线程B调用join()方法
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
		threadA.start(); // 启动线程A
		threadB = new Thread(new Runnable() {
			int count = 0;
			
			public void run() {
				while (true) {
					progressBar2.setValue(++count); // 设置进度条的当前值
					try {
						Thread.sleep(100); // 使线程B休眠100毫秒
					} catch (Exception e) {
						e.printStackTrace();
					}
					if (count == 100) // 当count变量增长为100时
						break; // 跳出循环
				}
			}
		});
		threadB.start(); // 启动线程B
	}
	
	// 设置窗体各种属性方法
	public static void init(JFrame frame, int width, int height) {
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(width, height);
		frame.setVisible(true);
	}
}



3.线程的中断
因为stop()方法在线程中不可控,所以现在在run()方法中使用无限循环的形式,然后使用一个boolean标记来控制循环的停止。
例:
public class InterruptTest{
private boolean isCon = false; //设置一个标记变量,默认值为false。

public void run(){
while(true){
 
....
if(isCon)
break; //当isCon变量为ture时停止线程
}
}
public void SetCon(){
this.isCon = true; //定义设置isCon变量为true的方法。
}
}
如果线程是使用了sleep()或wait()方法进入了就绪状态,可以使用Thread类中的interrupt()方法使线程离开run()方法,同时结束线程。
但程序会抛出InterruptException异常,用户可以在处理该异常时完成县城的终端处理。

//线程中断。
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
public class InterruptedSwing extends JFrame {
	Thread thread;
	public static void main(String[] args){
		init(new InterruptedSwing(),100,100);
	}
	public InterruptedSwing(){
		super();
		final JProgressBar proB = new JProgressBar();//创建进度条
		getContentPane().add(proB,BorderLayout.NORTH);
		proB.setStringPainted(true);				//设置进度条上显示数字
		thread = new Thread(new Runnable(){
			int count = 0;
			
			public void run(){
				while(true){
					proB.setValue(++count); //设置进度条当前值
					try{
						thread.sleep(1000);;	//使线程休眠1000ms
						}catch(InterruptedException e){
							System.out.println("当前线程中断");
							break;
						}
				}
			}
		});
		thread.start();
		thread.interrupt();			//中断线程。
	}
	public static void init(JFrame frame,int width,int height){
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(width, height);
		frame.setVisible(true);
	}
}



4.线程的礼让
使用yield()方法,但它仅仅只是给当下正在运行的线程一个提醒,告诉她可以将资源礼让,但这只是一种暗示,没有任意一种机制保证当前线程资源将资源礼让。

yield()方法使具有同样优先级的线程有进入可以执行的机会,当当前线程防止执行权时会再度回到就绪状态。


5.等待/唤醒机制:
1.wait();  让线程处于冻结状态,释放CPU执行权与执行状态。被wait的线程会被存储到线程池中。
2.notify(); 唤醒线程池中一个线程(任意)
3.notifyAll(); 唤醒线程池中的所有线程,让所有线程拥有执行资格。
class Resource
 {
	private String name;
	private String sex;
	private boolean flag=false;
	public synchronized void set(String name,String sex)
	{
		if(flag)
		try{
           this.wait();
		}catch(InterruptedException e){}
		this.name=name;
		this.sex=sex;
		flag=true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{
               this.wait();
				}catch(InterruptedException e){}
		System.out.println(name+":"+sex);
		flag=false;
		notify();
	}
 }
 
 class Input implements Runnable
 {
	 Resource r;
	 Input(Resource r)
	 {
		 this.r=r;
	 }
	 public void run()
	 {
		 int x=0;
		 while(true)
		 {
			
				 if(x==0)
				 {
					 r.set("test1","c");
					
				 }
				 else
				 {
					 r.set("test2","java");
				 }
          x=(x+1)%2;
			 }
			
		 }
	 }
 
 
 class output implements Runnable
 {
	 Resource r;
	 output(Resource r)
	 {
		 this.r = r;
	 }
	 public void run()
	 {
		 
		  while(true)
	     {
		   r.out();
				 
		 }
	 }
}
 
 
 class WaitNotifyDemo2
 {
	 public static void main(String[] args)
	 {   //创建对象
		 Resource r = new Resource();
		 //创建资源
		 Input in =new Input(r);
		 output out=new output(r);
		 //创建线程
		 Thread t1=new Thread(in);
		 Thread t2=new Thread(out);
		 //开启线程?
		 t1.start();
		 t2.start();
		 
	 }
 }


----------------------------------------------------------------------------------------------------

线程安全:

线程同步机制:
给共享资源加上一道锁,在一个线程访问该资源的时候其他线程只能等待。
1.同步块:
在JAVA中提供了同步机制,可以有效防止资源冲突,同步机制使用synchronized关键字。
将资源放置在同步块中,这个同步块也被称为临界区,它使用synchronize关键字建立,语法如下:
synchronized (object){

}
当其他线程获取到这个锁时,必须等待锁被释放才能进入该区域,Object 为任意一个对象,每个对象都存在一个标志位。,并具有两个值(0、1).
一个线程运行到同步块时首先检查该对象的标志位,如果为0,表明此时有线程在代码块中,这时该线程处于就绪态,等待同步块的锁被释放。
当该对象表示位为1时则执行代码块中代码,同时将Object对象的表示为设置为0;


2.同步方法。
同步方法就是在方法前面修饰synchronized关键字的方法,语法如下:
synchronized void f(){

}


这些方法都必须定义在同步中。
因为这些方法是用于操作线程状态的方法。
必须要明确到底操作的是那个锁上的线程。


为什么操作线程的方法wait notify.notifyAll定义在了object类中。
因为这些方法是监视器的方法,监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方法一定定义在object类中。

买票问题:避免线程错误

public class ThreadSell implements Runnable{
	int num = 20;

	public static void main(String[] args){
		ThreadSell t = new ThreadSell();
		Thread A = new Thread(t);
		Thread b = new Thread(t);
		Thread C = new Thread(t);
		Thread D = new Thread(t);
		
		A.start();
		b.start();
		C.start();
		D.start();

	}
	
	public synchronized void doit(){
	if(num>0){
		try{
			Thread.sleep(10);
		}catch(Exception e){
			e.printStackTrace();
		}
		System.out.println("tickets: "+--num);
	}
}


	public void run() {
		while(true){
			doit();
		}
	}


}


储户存钱:

class Bank
 {
     private int sum;
	 private object obj=new object();
     public synchronized void add(int num)//同步函数
	 {
		 sum=sum+num;
	     try{Thread.sleep(10);}catch (InterruptedException e){}//try catch抛出异常
		 System.ou.println("sum="+sum);
		
	 }	 
 }
 class Cus implements Runnable
 {
	 private  Bank b=new Bank();
	 public void run()
	 {
		
		 for(int x =0;x<3;x++)
		 {
			 b.add(100);
		 }
	 }
	 
 }
 class BankDemo
 {
	 public static void main(String[] args)
	 {
		 Cus c =new Cus();
		 Thread t1=new Thread(c);
		 Thread t2=new Thread(c);
		 t1.start();
		 t2.start();
	 }
 }


生产消费者问题:

Lock接口:替代了同步代码块或同步函数,将同步的隐式锁操作变成显式锁操作
同时更为灵活,可以一个锁上多组监视器。


lock():获取锁


unlock():释放锁,通常需要定义finally代码块中。


Condition接口:出现替代了object中的wait,notify,notifyAll方法
               将这些监视器方法单独进行了封装,变成了condition监视器对象
  可以任意锁进行组合。
   

import java.util.concurrent.locks.*;
class Resource
 {
	private String name;
	private int count =1;
	private boolean flag=false;
	//创建一个锁对象
	Lock lock = new ReentrantLock();
	//通过已有的锁获取该锁上的监视器对象
    //	Condition con = lock.newCondition();
	//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者
	Condition pro_con=lock.newCondition();
	Condition cos_con=lock.newCondition();
	
    public  void set(String name)
	{
		lock.lock();
		try{
		while(flag)
		try{
           pro_con.await();
		}catch(InterruptedException e){}
		this.name=name+count;
		count++;
		System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
		flag=true;
		cos_con.signalAll();
		}
		finally{
			lock.unlock();
		}
	}
	public void out()
	{
		lock.lock();
		try{
		while(!flag)
			try{
               cos_con.await();
				}catch(InterruptedException e){}
        System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);		
        flag=false;
		pro_con.signalAll();
		}
		finally{
		lock.unlock();
		}
	}
 }
 class Producter implements Runnable
 {
	private	Resource r;
	 Producter(Resource r)
	 {
		 this.r=r;
	 }
	 public void run()
	 {		
		 while(true)
		 {
			r.set("Set");
		
	    }
	}
 }
 
 class Custmer implements Runnable
 {
	private Resource r;
	 Custmer(Resource r)
	 {
		 this.r=r;
	 }
	 public void run()
	 {
		 while(true)
		 {
		 r.out();
	     }
	 }
}
 
 class ProducterCustmerDemo
 {
	  public static void main(String[] args)
	 {   //创建对象
		 Resource r = new Resource();
		 //创建资源
		 Producter in =new Producter(r);
		 Custmer out=new Custmer(r);
		 //创建线程
		 Thread t0=new Thread(in);  
		 Thread t1=new Thread(in); 
		 Thread t2=new Thread(out);
		 Thread t3=new Thread(out);
		 //开启线程?
		 t0.start();
		 t1.start();
		 t2.start();
		 t3.start();
		 
	 }
 }
 
 



猜你喜欢

转载自blog.csdn.net/Anddown/article/details/77891877