线程基本案例学习

一、每个java程序至少包含一个线程:主线程。其他线程都是通过Thread构造器或实例化继承类Thread的类来创建的。

 

public class MainThread {
	//每个java程序至少包含一个线程:主线程。其他线程都是通过Thread构造器或实例化继承类Thread的类来创建的                       
	public static void main(String[] args) {
	//调用Thread类currentThread()方法获取当前线程
	Thread t =	Thread.currentThread();
	System.out.println("主线程是:"+t);
		
	}

}
二、继承Thread类

package com;
/**
 * 
 * 解释结果:
 *  主线程名:main
	当前线程名:Thread-0
	当前线程名:mythread
	对于输出结构不仅不同机器之间的结果可能不同,而且在同一个机器上多次运行同一个程序也可能生成不同的结果,
 *  这是因为线程的执行次序是不定的,由操作系统控制,除非使用同步机制按特定的顺序执行。	
	注意:
	start()方法不能多次调用,如调用两次会抛出IllegalThreadStateException异常
 *	
 */
class Thread1  extends Thread{
	
	@Override
	public void run() {
		System.out.println("当前线程名:"+Thread.currentThread().getName());
	}
}

class  Thread2 extends Thread{
	public Thread2(String name) {
		super(name);
	}
	@Override
	public void run() {
		System.out.println("当前线程名:"+Thread.currentThread().getName());
	}
}

public class ThreadDemo {
	public static void main(String[] args) {
		System.out.println("主线程名:"+Thread.currentThread().getName());
		Thread1 t1 = new Thread1();
		Thread2 t2 = new Thread2("mythread");
		t1.start();
		t2.start();
		//t2.start();  //不能两次调用否则会抛出异常 
		
	}
}
控制台输出 

主线程名:main
当前线程名:Thread-0
当前线程名:mythread

三、实现Runnable接口实现线程

package com;
/**
 * 实现Runnable接口创建线程
 * 结果:随机产生结果
 * @author Administrator
 *
 */
class Renwu implements Runnable{

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName());
		for (int i = 0; i < 2000; i++) {
			System.out.println("A");
		}                 
		
	}
	
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
public class RunnableDemo {
	public static void main(String[] args) {
		Renwu rw = new Renwu() ;
		Thread t = new Thread(rw);
		t.start();
		System.out.println("主"+Thread.currentThread().getName());
		for (int i = 0; i < 2000; i++) {
			System.out.println("C");
		}
		
	}

}
结果产生随机,说明每个时刻随机执行一次线程。

四、线程的生命周期

新建:采用new语句执行创建完成。

就绪:执行start方法

运行:占用CPU

阻塞:执行了wait语句,执行了sleep语句和等待某个对象锁。等待输入的场合。

终止:退出run()方法。


package com;

class  LifeThread1 extends Thread {
	@Override
	public void run() {
		int i =0 ;
		while((++i)<1000){
			
		}
	}
}

public class LifeThread {
	public static void main(String[] args) throws InterruptedException {
		LifeThread1 t1 = new LifeThread1() ;
		System.out.println("等待状态"+t1.isAlive());
		t1.start();
		System.out.println("运行状态"+t1.isAlive());
		//join方法是等待线程结束
		t1.join();
		System.out.println("线程结束"+t1.isAlive());
	}
	/*等待状态false
	运行状态true
	线程结束false*/

	

}
五、案例

package com;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ButtonMove extends JFrame implements Runnable{
	
	JPanel p ;
	JButton btnStart ,btnStop,btnMove ;
	Thread t ;
	int movex=5 ;
	public ButtonMove() {
		p = new JPanel(null);
		btnStart= new JButton("开始");
		btnStop= new JButton("停止");
		btnMove =new JButton("左右移动");
		btnStart.setBounds(60,30,60,25);
		btnStop.setBounds(130,30,60,25);
		btnMove.setBounds(0,100,100,25);
		p.add(btnStart);
		p.add(btnStop);
		p.add(btnMove);
		this.add(p);
		this.setSize(400,300);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//注册监听
		btnStart.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				//创建线程对象
				t = new Thread(ButtonMove.this);
				//线程启动
				t.start();
				
			}
		});
		btnStop.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(t.isAlive()){
					//线程停止
					t.stop();
				}
				
			}
		});
	}

	@Override
	public void run() {
		while(t.isAlive()){
			int x =btnMove.getX()+movex ;
			int y = btnMove.getY();
			if(x<=0){
				x=0;
				movex=-movex ;
			}else if(x>=this.getWidth()-btnMove.getWidth()){
				x=this.getWidth()-btnMove.getWidth();
				movex=-movex ;
			}
			btnMove.setLocation(x,y);
			try {
				//休眠100毫秒
				t.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	public static void main(String[] args) {
		ButtonMove f = new ButtonMove() ;
		f.setVisible(true);
		
		
	}

}

sleep方法

1        Thread.sleep(毫秒)。

2        该方法作用是阻塞当前线程,让出CPU资源,让给其他线程。进入阻塞状态

3         

Interrupt()方法

打断休眠执行该方法会被catch到从而打断休眠

package com;
/**
 * 需求:  打断睡眠。
 * @author Administrator
 *
 */
public class InterruptTest {
	public static void main(String[] args) {
		Processor  p  = new Processor() ;
		p.setName("processor");   //设置线程名字
		p.start();
		p.interrupt();  //调用interrupt()方法会被catch到 
	}

}

class Processor extends Thread{
	
	@Override
	public void run() {
		try {
			Thread.sleep(10000000);
		} catch (InterruptedException e) {	
			//e.printStackTrace();
		}
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName()+""+i);
		}
	}
	
	
}

yield()方法

它与sleep()方法类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行。

package com;
/**
 * yield()方法
 *	
 */
class Thread1  extends Thread{
	
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+"---"+i);
			if(i%20==0){
				Thread1.yield();//让CPU片段  都有机会获取
			}
		}	
	}
}

class  Thread2 extends Thread{
	
	
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+"---"+i);
			
		}
	}
}

public class ThreadDemo {
	public static void main(String[] args) {
		//System.out.println("主线程名:"+Thread.currentThread().getName());
		Thread1 t1 = new Thread1();
		t1.setName("tone");
		Thread2 t2 = new Thread2();
		t2.setName("two");
		t1.setPriority(Thread.NORM_PRIORITY);
		t2.setPriority(Thread.NORM_PRIORITY);
		t1.start();
	
		t2.start();

		
	}
}




六、多线程案例

package com;

import java.awt.Color;
import java.awt.Font;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * 
 * 线程的最主要的功能是多任务处理,即多线程。多线程也就是在主线程中有多个线程在运行,多个线程的执行是‘并发’的
 *
 * tip: 什么是并发 并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,
 * 那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力
 *
 */
public class MultiThreadDemo extends JFrame {
	JPanel p;
	JLabel lbl;
	JButton btn;
	String s[] = { "你好", "欢迎", "121工程", "软件外包" };

	public MultiThreadDemo() {
		super("多线程");
		p = new JPanel();
		lbl = new JLabel("颜色");
		btn= new JButton(s[0]);
		lbl.setFont(new Font("宋体", Font.BOLD, 20));
		btn.setFont(new Font("黑体", Font.ITALIC, 20));
		p.add(lbl);
		p.add(btn);
		this.add(p);
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// 创建子线程
		new ColorChange().start();
		// 创建子线程
		new TextChange().start();

	}

	class ColorChange extends Thread {
		@Override
		public void run() {
			while (this.isAlive()) {
				int r = (int) (Math.random() * 256);
				int g = (int) (Math.random() * 256);
				int b = (int) (Math.random() * 256);
				lbl.setForeground(new Color(r, g, b));
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}
	}

	class TextChange extends Thread {
		@Override
		public void run() {
			int i = 0;
			while (this.isAlive()) {
				btn.setText(s[i++]);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (i == s.length) {
					i = 0;
				}
			}
		}
	}

	public static void main(String[] args) {
		MultiThreadDemo m = new MultiThreadDemo();
		m.setVisible(true);
	}

}
七、优先级别问题

package com;
/**
 * 
 * 当有多个线程同时处于可执行状态并等待获得CPU时间时,线程调度系统根据各个线程的优先级来绝定CPU分配时间
 * 优先级高的线程有“更大的机会”获得CPU时间
 * 默认情况下 优先级是Thread.NORM_PRIORITY定义是5
 * 可以通过set/getPriority()方法设置和获取  设置为MIN_PRIORITY(1) MAX_PRIORTY(10)之间
 *
 *注意:
 *1当线程睡眠后,优先级别就失效了,若想保证优先级别继续有效 可以考虑使用join()方法解决 --等待线程结束
 *2 线程优先级别依赖于操作系统,线程优先级别不能保证线程的执行次序,应尽量避免使用线程优先级为构建任务执行顺序的
 *绝对标准
 */
class Mythread extends Thread{
	public Mythread(String name) {
		super(name);
	}
	@Override
	public void run() {
		System.out.println(this.getName());
		try {
			sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class PriorityDemo  {
	public static void main(String[] args) {
		Mythread t1 = new Mythread("first");
		Mythread t2  =new Mythread("second");
		Mythread  t3 = new Mythread("third");
		t1.setPriority(Thread.MAX_PRIORITY);
		t2.setPriority(Thread.MAX_PRIORITY-1);
		t3.setPriority(Thread.MAX_PRIORITY-3);
		t1.start();
		t2.start();
		t3.start();
	}
	

}
八、使用对象锁实现同步

package com;
/**
 * JAVA使用监控器(对象锁)实现同步 ;每个对象都有一个对象锁。使用对象锁可以保证一次只允许一个线程执行对象的同步语句。
 *  
 * 方式有两种 
 * 第一种是   修饰调用的方法 前面加上synchronized void print(String str)
 * 第二种是 使用同步方法块修饰
 * 	@Override
	public void run() {
		synchronized (s) {
			s.print(str);
		}
	}
 *          
 *注意:synchronized锁定的是对象,而不是方法或代码块;synchronized也可以修饰类,
 *当用synchronized修饰 类的时候,表示这个类的所有方法都是synchronized的。
 */
class Share{
	
  	void print(String str){
		System.out.println("["+str);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("]");
	}
	
}
class Caller implements Runnable{
	Thread t ;
	String str ;
	Share s ;
	public Caller(String str, Share s) {
		this.str = str;
		this.s = s;
	 t = new Thread(this);
	 t.start();
	}



	@Override
	public void run() {
		synchronized (s) {
			s.print(str);
		}
	}
	
}


public class NoSyn {
	public static void main(String[] args) {
		Share s = new Share() ;
		Caller c1 = new Caller("客户A",s);
		Caller c2 = new Caller("客户B",s);
		Caller c3 = new Caller("客户C",s);
		
		
	}

}
九、线程同步会造成的问题,使用notify()和wait()方法处理。
package com;

/**
 * 线程同步会造成其他线程无法访问共享资源 ‘供需问题’
 * 
 * wait()方法可以让线程等待,释放对象锁 notify()和notifyAll()方法使线程之间互相通知事件的发生。
 * 
 * tip: wait()方法区别sleep wait会释放对象锁 而sleep不会
 *
 */
class Product {
	int n;
	// 为true时表示有值可取,为false时表示需要放入新值
	boolean valueSet = false;

	synchronized void get() {
		// 如果没有值,等待新值放入
		if (!valueSet) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "-GET()" + n);
		// 将valueSet设置为false表示值已取
		valueSet = false;
		// 通知等待线程,放入新值
		notify();
	}

	synchronized void put(int n) {
		// 如果没有值,等待线程取值
		if (valueSet) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		this.n = n;
		// 将valueSet设置为true 表示值已放入
		valueSet = true;
		System.out.println(Thread.currentThread().getName() + "-PUT" + n);
		// 通知等待线程,进行取值操作
		notify();
	}

}

class Prodcer implements Runnable {
	Product prodcut;

	public Prodcer(Product product) {
		this.prodcut = product;
		new Thread(this, "Proceduer").start();
	}

	@Override
	public void run() {
		int k = 0;
		// 生产5次
		for (int i = 0; i < 5; i++) {
			prodcut.put(k++);
		}

	}

}

class Consumer implements Runnable {
	Product prodcut;

	public Consumer(Product product) {
		this.prodcut = product;
		new Thread(this, "Consumer").start();
	}

	@Override
	public void run() {
		// 消费5次
		for (int i = 0; i < 5; i++) {
			prodcut.get();
		}

	}

}

public class WaitDemo {
	public static void main(String[] args) {
		// 共享的生产/消费实例
		Product product = new Product();
		// 指定生产线程
		Prodcer prodcer = new Prodcer(product);
		// 指定消费线程
		Consumer consumer = new Consumer(product);
	}

}
十、死锁问题

package com;
/**
 * 通过对象锁,可以很方便地实现数据同步,而对象锁引起的等候,很容易导致另一种问题-----‘死锁’
 * 所谓死锁,是指两个或多个线程都在等待对方释放对象资源而进入的一种不可‘调节’的状态。在程序设计
 * 中,死锁是无法预测或避开的,尽管这种情况并非经常出现,但一旦出现,程序的调试将变得异常艰难。
 * 
 *
 */
public class DeadLockDemo implements Runnable {
	private boolean flag ;
	//使用obj1 和obj2模拟两个对象资源
	static Object obj1 = new Object();
	static Object obj2 = new Object();
	

	@Override
	public void run() {
		String name =Thread.currentThread().getName();
		System.out.println(name+"flag:"+flag);
		/**
		 * 如果flag为true 先获取Obj1资源 等待500毫秒后获取Obj2资源
		 * 如果flag为false 先获取Obj2资源 等待500毫秒后获取Obj1资源
		 */
		if(flag){
			synchronized (obj1) {
				System.out.println(name+"休眠500毫秒,等待obj2");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (obj2) {
					System.out.println("获取obj2");
				}
			}
		}else{
			synchronized (obj2) {
				System.out.println(name+"休眠500毫秒,等待obj1");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				synchronized (obj1) {
					System.out.println("获取obj1");
				}
			}
		}
	}
	public static void main(String[] args) {
		
		DeadLockDemo d1 = new DeadLockDemo() ;
		d1.flag=true ;
		DeadLockDemo d2 = new DeadLockDemo() ;
		d2.flag=false ;
		Thread t1 = new Thread(d1);
		Thread t2= new Thread(d2);
		t1.start();
		t2.start();
		
		
}
}









    
       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值