Java线程和进程,Java线程进程
Java线程和进程,Java线程进程
Java应用程序的入口就是main方法()
启动一个Java应用程序,就是要运用它的main方法,这时候就启动了一个Java虚拟机------在Windows下查看任务管理器,就会发现多出了一个javaw.exe的进程,这个就是java虚拟机!而main()方法其实是Java虚拟机这个进程的一个主线程(默认至少还有一个垃圾回收器的守护线程,所以运行一个java应用程序,启动了一个java进程的同时,至少又启动了2个java线程)!main方法执行结束,java虚拟机自动就销毁了,进程就结束啦!
所以,我们同时运行了2个java类的main()方法,这时候操作系统会启动2个java进程。
但是,Java进程间是不能直接通信的
进程,是针对于操作系统而言的
线程,是java中一个重要的类,主要用来多个方法一起执行
进程,是针对于操作系统而言的,重量级,而且进程堆栈都是独立的,
线程是进程内部的单一的顺序流,堆共享,栈独立
========================================
原址:
http://blog.sina.com.cn/s/blog_638d75a20101jw39.html
======================================================================================
从计算机操作系统的发展来看,经历了这样的两个阶段:
单进程处理:最传统的DOS 系统中只要有病毒出现,则立刻有反映,因为在DOS 系统中属于进程处理,即:在同一个时间段上只能有一个程序在执行
多进程处理:windows操作系统是一个多进程,例如,假设在windows 中出现病毒了,则系统照样可以使用
那么对于资源来讲,所有IO设置、CUP等等都只有一个,那么对于多进程的处理来讲,在同一个时间段上会有多个程序运行,但是在同一个时间点上只能有一个程序运行
线程是在进程基础上的进一步划分,举个不恰当的例子来说:word 中的拼写检查,是在word整个程序运行中运行的。
所以,如果进程,则线程就消失,而如果线程消失的话,则进程依然会执行,未必会消失。
Java 本身是属于多线程的操作语言,所以提供了线程的处理机制。
线程实现的两种方式
在Java 中可以有两种方式实现多线程操作,一种是继承Tread类,另外一种是实现Runnable 接口
Thread 类
Thread 类是在java.lang 包中定义
一个类只要继承了Thread类,同时覆写了本类中的run()方法,则就可以实现多线程的操作了
[java] view plaincopyprint?
- 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);
- }
- }
- }
以上的类已经完成了多线程的操作类,那么下面就启动线程
[java] view plaincopyprint?
- 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()
[java] view plaincopyprint?
- 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()方法的定义:
[java] view plaincopyprint?
- 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 接口的定义:
[java] view plaincopyprint?
- public interface Runnable{
- public void run();
- }
所以,一个类只要实现了此接口,并覆写 run()方法
[java] view plaincopyprint?
- 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 实现的多线程
[java] view plaincopyprint?
- 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 类有如下的好处
避免单继承的局限,一个类可以同时实现多个接口
适合于资源的共享
以卖票的程序为例
[java] view plaincopyprint?
- 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--);
- }
- }
- }
- }
下面建立三个线程对象,同时卖票
[java] view plaincopyprint?
- 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 接口的话,则就可以实现资源的共享:
[java] view plaincopyprint?
- 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 类之间还是存在联系的:
[java] view plaincopyprint?
- public class Thread extends Object implements Runnable
发现Thread 类也是Runnable 接口的子类
原文: http://blog.csdn.net/iquicksandi/article/details/8470692
相关文章
- 暂无相关文章
用户点评