Java 进程与线程

从计算机操作系统的发展来看,经历了这样的两个阶段:

单进程处理:最传统的DOS 系统中只要有病毒出现,则立刻有反映,因为在DOS 系统中属于进程处理,即:在同一个时间段上只能有一个程序在执行

多进程处理:windows操作系统是一个多进程,例如,假设在windows 中出现病毒了,则系统照样可以使用



那么对于资源来讲,所有IO设置、CUP等等都只有一个,那么对于多进程的处理来讲,在同一个时间段上会有多个程序运行,但是在同一个时间点上只能有一个程序运行


线程是在进程基础上的进一步划分,举个不恰当的例子来说:word 中的拼写检查,是在word整个程序运行中运行的。

所以,如果进程,则线程就消失,而如果线程消失的话,则进程依然会执行,未必会消失。


Java 本身是属于多线程的操作语言,所以提供了线程的处理机制。


线程实现的两种方式

在Java 中可以有两种方式实现多线程操作,一种是继承Tread类,另外一种是实现Runnable 接口


Thread 类


Thread 类是在java.lang 包中定义

一个类只要继承了Thread类,同时覆写了本类中的run()方法,则就可以实现多线程的操作了


package org.threaddemo;

public class MyThread extends Thread{
	private String name; //定义name 属性
	
	public MyThread(String name){
		this.name = name;
	}
	
	public void run(){ //覆写run()方法
		for (int i=0;i<50;i++){ // 表示循环50次
			System.out.println("Thread 测试"+this.name+" i:"+i);
		}
	}

}


以上的类已经完成了多线程的操作类,那么下面就启动线程


package org.threaddemo;

public class ThreadDemo02 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		MyThread th1 = new MyThread("A类");
		MyThread th2 = new MyThread("B类");
		
		th1.run();
		th2.run();
	}

}


但是,此时的执行可以发现非常的有规律,先执行完第一个对象,再执行第二个对象,也就是说并没有实现交互的运行

从JDK的文档中可以发现,一旦调用strat()方法,则会通过JVM找到run()方法


public void start()


package org.threaddemo;

public class ThreadDemo02 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		MyThread th1 = new MyThread("A类");
		MyThread th2 = new MyThread("B类");
		
		th1.start();
		th2.start();
	}

}


此时,程序已经可以正常的进行交互式的运行了。

但是,需要思考的是,为什么非要使用start()方法启动多线程呢?

在JDK 的安装路径下,src.zip是全部的java 源程序,通过此代码找到 Thread 类中的 start()方法的定义:


public synchronized void start(){ //定义的start()方法
	if (started) //判断线程是否已经启动
		throw new IllegalThreadStateException();
	started = true;//如果没有启动则修改状态
	start0();//调用start0()方法
}

private native void start0(); //使用 natvie 关键字声明的方法,没有方法体


操作系统有很多种,Windows、Linux、UNIX,既然多线程操作中要进行CPU资源的强占,也就是说要等待CPU调度,那么这些调度的操作是由各个操作系统的低层实现的,所以在java程序中根中就没法实现,那么此时Java的设计者定义了native 关键字,使用此关键字表示可以调用操作系统的低层函数,那么这样的技术又称为JNI技术(Java Native Interface)

而且,此方法在执行的时候将调用run()方法完成,由系统默认调用的

但是,第一种操作中有一个最大的限制,一个类只能继承一个父类


Runnable 接口


在实际的开发中一个多线程的操作类很少去使用Thread 类完成,而是通过Runnable 接口完成。

观察Runnable 接口的定义:


public interface Runnable{
	public void run();
}

所以,一个类只要实现了此接口,并覆写 run()方法


package org.threaddemo;

public class RunnableDemo implements Runnable{ //实现Runnable 接口
	private String name; // 定义name 属性
	
	public RunnableDemo(String name){
		this.name = name;
	}
	
	public void run(){ //覆写run()方法
		for (int i=0;i<50;i++){ //表示循环10次
			System.out.println("Thread 测试"+this.name+" i:"+i);
		}
	}

}

完成之后,下面继续启动多线程

但在现在使用Runnable 定义的子类中并没有start()方法,而只有Thread类中才有

在Thread 类中存在以下的一个构造方法:


public Thread(Runnable target)


此构造方法接收Runnable 的子类实例。也就是说现在可以通过Thread 类中启动 Runnable 实现的多线程


package org.threaddemo;

public class ThreadDemo02 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		MyThread th1 = new MyThread("A类");
		MyThread th2 = new MyThread("B类");
		
		new Thread(th1).start(); //调用线程体
		new Thread(th2).start(); //调用线程体
	}

}

以上的操作代码也属于交替的运行,所以此时程序也同样实现了多线程的操作


两种实现方式的区别及联系


在程序的开发中只要是多线程则肯定永远以实现Runnable 接口为正统操作,因为实现Runnable 接口相比继承 Thread 类有如下的好处

避免单继承的局限,一个类可以同时实现多个接口

适合于资源的共享


以卖票的程序为例


public class TicketsDemo extends Thread { //继承 Thread
	private int TiceketsDemo = 5; // 一共才5张票
	
	public void run(){ //覆写 run()方法
		for (int i=0;i<50;i++){ //表示循环50次
			if (this.TiceketsDemo>0){ 
				System.out.println("出票:"+this.TiceketsDemo--);
			}
		}
	}

}

下面建立三个线程对象,同时卖票


package org.threaddemo;

public class ThreadDemo03 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TicketsDemo tic1 = new TicketsDemo(); //一个线程
		TicketsDemo tic2 = new TicketsDemo(); //一个线程
		TicketsDemo tic3 = new TicketsDemo(); //一个线程
		
		tic1.start(); //开始卖票
		tic2.start(); //开始卖票
		tic3.start(); //开始卖票
	}

}

发现现在一共买了15张票,但是实际上只有5张票。所以证明每一个线程都买自己的票,没有达到资源共享的目的


那么,如果现在实现的是Runnable 接口的话,则就可以实现资源的共享:


package org.threaddemo;

public class ThreadDemo03 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TicketsDemo tic1 = new TicketsDemo();
		
		new Thread(tic1).start();
		new Thread(tic1).start();
		new Thread(tic1).start();
	}

}

虽然现在程序中有三个线程,但是三个线程一共才卖出了5张票。也就是说使用Runnable 实现的多线程可以达到资源共享的目的。

实际上 Runnable 接口和Thread 类之间还是存在联系的:


public class Thread extends Object implements Runnable

发现Thread 类也是Runnable 接口的子类



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值