线程

线程--什么是进程

进程--概念

要解释线程,就必须明白什么是进程,就好象要搞清中国历史,就必须要了解春秋战国。

什么是进程呢?

    进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击左面的IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。目前操作系统都支持多进程。

要点:用户每启动一个进程,操作系统就会为该进程分配一个独立的内存空间。

 

线程--概念

在明白进程后,就比较容易理解线程的概念。

什么是线程呢?

    是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。线程有就绪、阻塞和运行三种基本状态。

线程

1、线程是轻量级的进程

2、线程没有独立的地址空间(内存空间)

3、线程是由进程创建的(寄生在进程)

4、一个进程可以拥有多个线程-->这就是我们常说的多线程编程

5、线程有几种状态:

  a、新建状态(new)

  b、就绪状态(Runnable)

  c、运行状态(Running)

  d、阻塞状态(Blocked)

  e、死亡状态(Dead)

 

线程有什么用处

java程序中流传一句话,不会使用线程就别跟别人说自己学过java。目前绝大部分应用程序都会涉及到多并发的问题。只要应用程序涉及到并发,就离不开多线程编程。

 

线程--如何使用

在java中一个类要当作线程来使用有两种方法

1、继承Thread类,并重写run函数

2、实现Runnable接口,并重写run函数

因为java是单继承的,在某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能java设计者们提供了另外一个方式创建线程,就是通过实现Runnable接口来创建线程。

/**
 * 演示如何通过继承Thread来开发线程
 */
public class Thread01 {
	public static void main(String[] args) {
		//创建一个 Cat对象
		Cat cat=new Cat();
		//启动线程
		cat.start();//.start()会导致run函数运行
	}
}

class Cat extends Thread{
	int times=0;
	//重写run函数
	public void run(){
		while(true){
			//休眠一秒
			//1000表示1000毫秒
			try {
				Thread.sleep(1000);//sleep就会让该线程进入到Blocked阻塞状态,并释放资源。
			} catch (Exception e) {
				e.printStackTrace();
			}
			times++;
			System.out.println("hello,world!"+times);
			if(times==10){
				//退出线程
				break;
			}
		}
	}
}

通过Runnable接口来实现建立线程实例

/**
 * 演示如何通过Runnable接口来开发线程
 */
public class Thread02{
	public static void main(String []args){
		Dog dog=new Dog();
		//创建线程
		Thread t=new Thread(dog);
		//启动线程
		t.start();
	}
}
class Dog implements Runnable{//创建Runnable接口
	public void run(){//重写run函数
		int times=0;
		while(true){
			try{
				Thread.sleep(1000);
			}catch (Exception e) {
				e.printStackTrace();
			}
			times++;
			System.out.println("hello,wrold!"+times);
			if(times==10){
				break;
			}
		}
	}
}

多线程实例演示

/**
 *多线程Thread使用
 *1、一个线程通过接收n来执行1+..+n得到和
 *2、另一线程每隔1秒输出一次hello world!
 */
public class Thread03 {
	public static void main(String[] args) {
		Pig pig=new Pig(10);
		Bird bird=new Bird(10);
		//建立线程
		Thread t1=new Thread(pig);
		Thread t2=new Thread(bird);
		//启动线程
		t1.start();
		t2.start();
	}
}

//打印hello world!
class Pig implements Runnable{
	int n=0;
	int times=0;
	public Pig(int n){
		this.n=n;
	}
	
	public void run(){
		while(true){
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			times++;
			System.out.println("我是一个线程,正在输出第"+times+"个hello world!");
			if(times==n){
				break;
			}
		}
	}
}

//算数学题
class Bird implements Runnable{//多线程时应使用implements接口来实现,不要使用extends继承
	int n=0;
	int res=0;
	int times=0;
	public Bird(int n){
		this.n=n;
	}
	
	public void run() {
		while(true){
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			res+=(++times);
			System.out.println("当前结果是:"+res);
			if(times==n){
				System.out.println("最后的结果是:"+res);
				break;
			}
		}
	}
}

线程--区别

线程--继承Thread VS实现Runnable的区别

    从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口,如果一定要说它们有什么区别,总结几点

1、尽可能使用实现Runnable接口的方式来创建线程

2、在使用Thread的时候只需要new一个实例出来,调用start()方法即可以启动一个线程,如:   Thread test=new Thread();

        test.start();

3、在使用Runnable的时候需要先new一个实现Runnable的实例,之后用Thread调用,如:

    Test implements Runnable

    Test t=new Test();

    Thread test=new Thread(t);

    tset.start();

 

线程--深入理解

线程对象只能启动一个线程

/**
 * 功能:使用线程的注意事项
 * 不论继承Thread或实现Rnunable接口都不能使用start启同一个线程2次
 */
public class Thread04 {
	public static void main(String[] args) {
		Cat cat1=new Cat();
		cat1.start();
		//cat1.start();同一个线程,不能启动2次
		
		Dog dog1=new Dog();
		Thread t=new Thread(dog1);
		t.start();
		//t.start();同一个线程,不能启动2次
	}
}

//猫类
class Cat extends Thread{
	public void run(){
		System.out.println("11");
	}
}

//狗类
class Dog implements Runnable{
	public void run(){
		System.out.println("2");
	}
}

结论:不管是通过继承Thread,还是通过实现Runnable接口创建线程,它们的一个对象只能启动(即:start())一次。否则就会有异常抛出。

 

两种创建线程的方法的区别

创建线程有两种方法:1、继承Thread;2、实现Runnable接口;这两种方法有什么区别?

用实现Runnable接口的特点

1、用实现Runnable接口的方法创建对象可以避免java单继承机制带来的局限;

2、用实现Runnable接口的方法,可以实现多个线程共享同一段代码(数据);

因此建议大家如果你的程序有同步逻辑需求,则使用Runnable的方法来创建线程。

 

java线程的同步--提出问题

多线程的并发,给我们编程带来很多好处,完成更多更有效率的程序。但是也给我们带来线程安全问题。

 

java线程的同步--解决问题

解决问题的关键就是要保证容易出问题的代码的原子性所谓原子性就是指:当a线程在执行某段代码的时候,别的线程必须等到a线程执行完后,它才能执行这段代码。也就是排队一个一个解决。

java处理线程两步的方法非常简单,只需要在需要同步的代码段,用:

    synchronized(Object){你要同步的代码}

即可。

售票案例演示

/**
 * 功能:使用线程的注意事项
 * 线程并发同步锁synchronized(Object){}的使用
 */
public class Thread05 {
	public static void main(String[] args) {
		//定义一个售票窗口
		TicketWindow tw1=new TicketWindow();
		
		//使用三个线程同时启动
		Thread t1=new Thread(tw1);
		Thread t2=new Thread(tw1);
		Thread t3=new Thread(tw1);
		
		t1.start();
		t2.start();
		t3.start();
	}
}

//售票窗口类
class TicketWindow implements Runnable {
	//共有2000张票
	private int nums=2000;
	private Dog myDog=new Dog();

	public void run() {
		while(true){
			//出票速度是1秒出一张
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}

			//认为if else要保证其原子性
			//先判断是否还有票
			synchronized(myDog){//synchronized(this){}为同步代码块
				if(nums>0){
					//显示售票信息
					//Thread.currentThread().getName()得到当前线程的名字
					System.out.println(Thread.currentThread().getName()+"正在售出第"+nums+"张票");
					nums--;
				}else{
					//售票结束
					break;
				}
			}
		}
	}
}

class Dog{
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值