码迷,mamicode.com
首页 > 编程语言 > 详细

Java多线程及其使用(一)

时间:2015-05-27 10:14:43      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:多线程   java   并发   线程   

Java多线程对我来说一直是个高级而且神秘的东西,那么今天有幸也正好有时间讲解一下Java的多线程。

首先线程的概念及定义就不说了

1.创建线程三种方式:1.继承Thread 2.实现Runnable接口 3.实现Callable接口

继承Thread

public class FirstThread extends Thread{
	private int i;
	public void run(){
		for(;i<100;i++){
			System.out.println(getName()+" "+i);
		}
	}
	public static void main(String[] args){
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName());
			if(i == 20){
				new FirstThread().start();
				new FirstThread().start();
			}
		}
	}

}

实现Runnable

public class SecondThread implements Runnable{
	private int i;
	public void run(){
		for(;i<100;i++){
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}
	public static void main(String[] args){
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName()+" "+i);
			if(i == 20){
				SecondThread st = new SecondThread();
				new Thread(st,"新线程1").start();
				new Thread(st, "新线程2").start();
			}
		}
	}

}

实现Callable

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;


public class ThirdThread implements Callable<Integer>{
	public Integer call(){
		int i=0;
		for(;i<100;i++){
			System.out.println(Thread.currentThread().getName()+"的循环变量i的值"+i);
		}
		return i;
	}
	public static void main(String[] args){
		ThirdThread rt = new ThirdThread();
		FutureTask<Integer> task = new FutureTask<Integer>(rt);
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName()+"的循环变量i的值"+" "+i);
			if(i==20){
				new Thread(task, "有返回值的线程").start();
			}
		}
		try{
			System.out.println("子线程的返回值:"+task.get());
		}catch(Exception e){
			e.printStackTrace();
		}
	}

}

简单说明:Callable更像是Runnable的增强版,所以可以归为一类,所以大体上创建线程的方式只有两种,对于使用Thread方式好,还是Runnale方式好,这里推荐Runnale方法,因为如果采用继承Thread方法就不能继承其它父类,相比之下,Runnale则更加灵活

2.线程的生命周期(这里以网上收集的一幅图来说明)

技术分享

3.线程的控制

(1)join()方法:作用是如果在运行当前线程的时候中途你又调用另一线程,那么当前线程先暂停执行,把另一线程执行完后在继续执行

(2)守护线程:作用是为其它线程提供服务,而且又在后台运行,所以又叫后台线程

(3)线程睡眠:使用sleep方法,可以理解为在睡眠这段时间内指定的线程都不会执行(就让它一直睡下去),即在指定时间内的线程无效(这是为了帮助理解,片面的说法)

(4)线程让步:使用yield方法,可以理解为在指定时间内指定的线程不执行,过了这段时间,在执行(只是暂停,目的是为了想让其它线程执行)

(5)优先级的设置:字面意思就可以理解,就不再阐述

4.线程的同步(意思就是线程按先后顺序依次执行)

试想如果线程不同步,就会出现不按顺序执行,就会出现线程同时执行,这样就会出大问题

如果多个线程异步(不同步)访问,就出问题了,比如典型的银行存款取款问题,这是类似生产者和消费者的问题(其实很简单,意思就是一个人赚钱一个人花钱),如果存款和取款同时操作,我们就会出现很多问题,比如作为取款方,系统要对取款进行钱的减量操作,但是另一个人又在存,而且同一时间,我的减量操作到底是存了后的还是存了前的?作为存款方,系统对存款进行增量操作,但是我的增量操作,到底是取了后的还是取了钱的,那么系统就会出问题了,那么银行要是这么搞,你会高兴还是悲伤呢,自己的钱老是出问题。

所以,多个线程访问同样资源时,我们要进行同步操作,同步操作有以下几种方式

(1).使用synchronized:可以对方法进行锁定,可以理解为,每个线程有一把钥匙,你执行这个方法,方法使用synchronized就会加锁,你要你的线程只有一个能到达锁前开锁,每个线程访问都会对该方法锁定;也可以对代码块锁定,大家都知道,函数方法就是代码写的,那么方法能锁定代码块也能锁定

对方法锁定

public synchronized void 方法名(锁定的参数(比如银行账户)){

方法的实现

}

对代码块的锁定

synchronized(锁定的参数(比如银行账户)){

代码的实现

}

(2).使用同步锁Lock:这个方法比synchronized更强大,主要体现在:更为广泛的锁定操作,因此实现起来更为灵活,比较好的东西也比较重要,但是使用方法差不多,所以这里不做详细介绍

4.2.死锁:是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去(感觉不是很好理解,可以查阅相关资料)

5线程的通信,有以下几种方式

(1)对于synchronized借助Object类提供的wait(),notify,nitifyAll()三个方法,我们从字面意思就可以大体理解他们的作用

(2)如果使用Lock对象,则要使用Condition来控制,借助await(),signal,signalAll(),是不是感觉和synchronized的通信控制比较相似,那么我们也可以以字面意思来理解它们的大体作业

(3)使用阻塞队列(BlockingQueue),这是Java5提供的一个接口BlockigQueue,使用put(),take(),方法,

6.线程组,线程池,线程相关的工具ThreadLoacl及安全的线程集合(主要对不安全的集合进行包装,使之安全)以后再做介绍


最后是线程的使用:

我们学习了线程最为困惑的是什么时候我们使用多线程:

1.要处理的数据比较庞大(比如对数据库的数据进行分析)

2.并发控制,一般采用线程池技术

时间不够了,就暂时写到这里吧,写的不是很详细,有时间再补充上去,对了,这里推荐一个网站给大家吧,并发编程网,我感觉里面的东西非常好,所以有时间一定要去看看,如果你对多线程技术感兴趣的话



Java多线程及其使用(一)

标签:多线程   java   并发   线程   

原文地址:http://blog.csdn.net/lsx991947534/article/details/46040887

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!