`

java多线程

阅读更多

      java多线程是java基础中的重点,下面就java的多线程进行详细讲解。

1、进程和线程概念

      进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。
      线程是指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
2、线程实现的两种方式

      在java中,实现多线程的方式有两种,一个是继承Thread类,另一个是实现Runnable接口。

      (1)继承Thread类方法

      在java中,一个类如果继承Thread类,同时覆写本类的run()方法,则该类就实现了多线程的操作。在操作多线程时,我们需要通过该类的实例去调用多线程的start()方法,该方法一旦被调用,JVM会自动调用run()方法。当有多个类的实例启动start()方法。则程序会进行交互式的运行run()方法体的内容,如下程序就证明了这点。该方法一个类只能继承一个父类,所以比较有限,start方法中通过JNI技术调用操作系统的底层函数实现的。

 代码如下:

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++) {// 表示循环10次
			System.out.println("Thread运行:" + name + ",i = " + i);
		}
	}
}
public class ThreadDemo{
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A");
		MyThread mt2 = new MyThread("线程B");
		mt1.start(); // 调用线程体
		mt2.start(); // 调用线程体

	}
}

 运行结果:

Thread运行:线程A,i = 0
Thread运行:线程A,i = 1
Thread运行:线程A,i = 2
Thread运行:线程A,i = 3
Thread运行:线程A,i = 4
Thread运行:线程A,i = 5
Thread运行:线程A,i = 6
Thread运行:线程A,i = 7
Thread运行:线程A,i = 8
Thread运行:线程A,i = 9
Thread运行:线程A,i = 10
Thread运行:线程A,i = 11
Thread运行:线程A,i = 12
Thread运行:线程A,i = 13
Thread运行:线程A,i = 14
Thread运行:线程A,i = 15
Thread运行:线程A,i = 16
Thread运行:线程A,i = 17
Thread运行:线程A,i = 18
Thread运行:线程A,i = 19
Thread运行:线程B,i = 0
Thread运行:线程A,i = 20
Thread运行:线程B,i = 1
Thread运行:线程A,i = 21
Thread运行:线程B,i = 2
Thread运行:线程A,i = 22
Thread运行:线程B,i = 3
Thread运行:线程A,i = 23
Thread运行:线程B,i = 4
Thread运行:线程A,i = 24

 (2)实现Runable接口方法

         该方式是一个类implements Runable接口中的run方法,Runnable接口中只有一个run方法。要启动该类实现多线程方法,还要借助Thread类,因为Thread类的构造方法的参数是一个Runable接口,通过将该类传入到Thread类中的构造函数中实现了线程的启动,从而实现程序的多线程交互操作。

public class MyThread implements Runnable { // 实现Runnable接口
	private String name; // 定义name属性

	public MyThread(String name) {
		this.name = name;
	}

	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			System.out.println("Thread运行:" + name + ",i = " + i);
		}
	}
}

 

public class RunnableDemo01 {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A");
		MyThread mt2 = new MyThread("线程B");
		new Thread(mt1).start(); // 调用线程体
		new Thread(mt2).start(); // 调用线程体
	}
}

(3)两种实现方式的区别和联系

        在软件的开发过程中,实现Runable接口的方法是正统操作,因为实现Runnable接口比继承Thread类具有如下的优点:

(I) 避免了单一继承的局限,一个类可以实现多个接口。

(II)适合于资源共享。

       下面以买票的例子来说明资源的共享,已知一共有五张票,同时启动3个线程进行买票,继承Thread接口的不能实现资源共享,而实现Runnable接口的可以实现资源共享。

public class MyThread extends Thread {// 继承Thread类
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			if (this.ticket > 0) {
				System.out.println("卖票:ticket = " + this.ticket--);
			}
		}
	}
}
public class ThreadTicket {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread(); // 一个线程
		MyThread mt2 = new MyThread(); // 一个线程
		MyThread mt3 = new MyThread(); // 一个线程
		mt1.start() ;	// 开始卖票
		mt2.start() ;	// 开始卖票
		mt3.start() ;	// 开始卖票
	}
}

 测试结果:每个线程各自卖各自的票,并未实现资源共享。

卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1

 而Runnable接口却实现了资源的共享

public class MyThread implements Runnable {// 实现Runnable接口
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			if (this.ticket > 0) {
				System.out.println("卖票:ticket = " + this.ticket--);
			}
		}
	}
}
public class RunnableTicket {
	public static void main(String[] args) {
		MyThread mt = new MyThread(); // 一个线程
		new Thread(mt).start() ;	// 开始卖票
		new Thread(mt).start() ;	// 开始卖票
		new Thread(mt).start() ;	// 开始卖票
	}
}

 测试结果:

卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1

      由于Thread类本身继承object类,同时实现了Runnable接口,而我们实现的Runnable接口,在启动线程过程中通过Thread类的构造函数传出我们实现的类,其实里面存在代理模式的设计。


 

 

 3、线程的状态

 

 线程基本的五个状态:创建(start),可执行(Runnable),被阻塞(blocked),运行(running)和结束 (death)状态。

4、线程的操作

(1)基本操作


 java在运行的时候,至少要启动2个线程,一个是主线程,一个是gc线程。

(2)状态操作

 判断线程状态的方法:public final boolean isAlive();注意线程的每次运行状态是不一致的。

(3)强制线程的执行

 在一个线程A执行过程中,可以强行让B线程加入执行,等待B线程按规定执行完毕后再继续执行A线程,则可以用join()方法完成该需求。

(4)线程的睡眠

 thread.sleep()可以让线程进入阻塞状态。

(5)线程的中断

(6)线程的优先级



 注意:主线程的优先级默认为普通优先级。

(7)等待与通知

wait(),notify()与notifyall()是Object定义的方法,可以通过这三个方法控制线程释放对象的锁定。或者通知线程参与锁定竞争。

wait()可以指定等待时间,时间到后线程加入排班,如果指定时间0或不指定,则线程会持续等待,直到被中断(调用interrupt())或是告知(notify())可以参与排班。

下面就wait()notify()的应用,生产者和消费者问题

package com.jason.util;

public class Clerk {
	
	private int product = -1;//只有一个产品存储空间,-1表示没有产品
	
	/**
	 * @param product
	 */
	public synchronized void setProduct(int product){
		while(this.product != -1){
			try {
				wait();		//目前没有空间放产品处于等待状态
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
		this.product = product;
		System.out.println("生产者设定"+this.product);
		notify();			//通知等待中的线程如消费者
	}
	
	/**
	 * @return
	 */
	public synchronized int getProduct(){
		
		while(this.product == -1){
			try {
				wait();		//目前没有产品,处于等待状态
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
		
		int p = this.product;
		System.out.println("消费者取走"+this.product);
		this.product = -1;	//表示货品被取走
		notify();			//通知等待中的线程如生产者
		return p;
	}
}

 

package com.jason.util;

public class Producer implements Runnable {
	
    private Clerk clerk; 
    
    public Producer(Clerk clerk) { 
        this.clerk = clerk; 
    } 
    
    public void run() { 
        System.out.println("生产者开始生产整数......"); 
        for(int product = 1; product <= 10; product++) { 
            try { 
                Thread.sleep((int) (Math.random() * 3000)); 
            } 
            catch(InterruptedException ex) { 
                throw new RuntimeException(ex);
            } 
            clerk.setProduct(product); 
        }       
    } 
}

 

package com.jason.util;

public class Consumer implements Runnable {

	private Clerk clerk;

	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}

	@Override
	public void run() {
		
		System.out.println("消费者开始消费整数。。。。。");
		
		for(int i = 1; i <=10;i++){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
			int product = clerk.getProduct();
		}
	}
}

 

package com.jason.util;

public class ProductConsumerDemo {

	 public static void main(String[] args) {
        Clerk clerk = new Clerk(); 
        new Thread(new Producer(clerk)).start(); 
        new Thread(new Consumer(clerk)).start(); 
	 }    
}

 运行结果:

生产者开始生产整数......
消费者开始消费整数。。。。。
生产者设定1
消费者取走1
生产者设定2
消费者取走2
生产者设定3
消费者取走3
生产者设定4
消费者取走4
生产者设定5
消费者取走5
生产者设定6
消费者取走6
生产者设定7
消费者取走7
生产者设定8
消费者取走8
生产者设定9
消费者取走9
生产者设定10
消费者取走10

 

 

  • 大小: 12.3 KB
  • 大小: 23.4 KB
  • 大小: 51.4 KB
  • 大小: 40.2 KB
  • 大小: 35.7 KB
  • 大小: 21.9 KB
  • 大小: 52.5 KB
分享到:
评论
2 楼 gaojiewyh 2009-07-16  
不是忽悠人,这段时间在做DAO的学习,没及时跟新java多线程的东西
1 楼 sailinglee 2009-07-14  
哪有这样忽悠人的哦 

相关推荐

    Java多线程设计模式上传文件

    Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    java多线程ppt

    java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题

    java 多线程操作数据库

    一个java 多线程操作数据库应用程序!!!

    java多线程经典案例

    java多线程经典案例,线程同步、线程通信、线程阻塞等经典案例

    Java多线程编程技术

    《Java多线程编程核心技术》建议猿友们读两遍,因为其写得没有那么抽象,第一遍有些概念不是很理解,可以先跳过并记录起来,第一遍阅读的目的主要是了解整个架构。第二遍再慢慢品味,并贯穿全部是指点来思考,并将...

    Java多线程编程实战指南(核心篇)

    Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...

    Java多线程知识点总结

    该文档总结了Java多线程相关的知识点,分享给大家,简单易懂!

    java多线程的讲解和实战

    详细的讲解了java多线程的原理,并配有代码进行实战,适合java初学者和想对多线程有进一步了解的人。

    java多线程通信图解

    一张图方便理解和掌握java 多线程之间通信的实质 java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,...

    java多线程处理数据库数据

    java多线程处理数据库数据,使用并发包,无框架,可批量处数据库数据,进行增删改。。等等操作。

    java多线程,对多线程,线程池进行封装,方便使用

    java多线程,对多线程,线程池进行封装,方便使用

    Java多线程编程经验

    现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 线程是指进程中的一个执行流程,一个进程中可以运行多个线程。...本文档提供Java多线程编程经验,方便广大Java爱好者研究学习Java多线程

    java多线程处理大数据

    java多线程处理大数据,可根据配置的线程数,任务去调度处理

    java多线程并发

    java多线程并发的在新窗口

    Java多线程机制(讲述java里面与多线程有关的函数)

    Java多线程机制 9.1 Java中的线程 9.2 Thread的子类创建线程 9.3 使用Runable接口 9.4 线程的常用方法 9.5 GUI线程 9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 ...

    java多线程核心技术

    资深Java专家10年经验总结,全程案例式讲解,首本全面介绍Java多线程编程技术的专著 结合大量实例,全面讲解Java多线程编程中的并发访问、线程间通信、锁等最难突破的核心技术与应用实践 Java多线程无处不在,如...

    java多线程实现大批量数据导入源码

    java多线程实现大批量数据切分成指定份数的数据,然后多线程处理入库或者导出,线程的个数和每份数据的数量都可以控制

    java多线程查询数据库

    java多线程并发查询数据库,使用线程池控制分页,并发查询。

    java多线程模拟队列实现排队叫号

    java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号 java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号

Global site tag (gtag.js) - Google Analytics