一、多线程的概念
1、程序 、进程、和线程
程序(program)是一组计算机指令的有序集合,程序保存在储存介质上(如硬盘),是静态的。
进程(Process)是程序在CPU上的一次执行过程 ,是活跃在内存中的,这经动态的,当运行一个程序时,就是启动了一个进程。操作系统通过分配内存、CPU时间片等资源为正在运行的程序提供运行环境,并可以实现多个进程的并发运行。
线程(Thread)则是进程中某个单一顺序的控制流,是进程的一部分。
线程与进程的区别:
线程的划分尺度小于进程,使得多线程程序的并发性高。进程在执行过程中拥有独立的内存单元,而多个线程则是共享内存,从而极大地提高运行效率。进程是一个独立的执行单元,而线程不能独立执行,必须依赖进程,由进程提供多个线程的执行控制。
2、多线程
一个简单的程序在运行时只有一个线程,这种程序是单线程。多线程允许一个进程创建多个线程,并且可以并发的执行多个线程。
二、多线程的实现
1、创建线程的两种方式
(1)、继承Thread类 ,
public class DefineThread extends Thread
{
public void run(){}//将要在线程上执行的代码放到run方法中
}
实例化Thread类
DefineThread thread=new DefineThread();
thread.start();//启动这个线程
2、实现Runnable接口
new Thread(new Runnable()//定义一个匿名线程类,添加一个实现Runnable接口的匿名类
{
public void run()
{
//方法体
}
}
).start();//启动这个线程
3、 线程的基本方法
void start()启动一个线程,这个方法将产生一个新的线程
static void sleep(long time)//让线程休眠time长毫秒
static Thread Thread.currentThread()获得当前线程
void setPriority(int newPriority) 更改线程的优先级
static void yield() 暂停当前正在执行的线程对象,并执行其它具有相同或更高优先级的线程
4.后台线程与联合线程
(1)、前台线程,如果我们对某个线程对象在启动之前调用了setDaemon(true)方法,那么这上线程就变成了前台线程,反之,这个线程则为后台线程。对java程序 来说。只要还有一个前台线程在运行,这个进程就不会结束。如果这个进程中只有后台线程运行,这个进程就会结束 。
(2)、联合线程
final void join() 使用这个方法可以使调用这个方法的线程执行完了后,才开始执行其它的线程
final void join(int time)//等待多少秒后线程又开始交替执行。
5、线程的状态和生命周期
一个线程从创建、启动到终止的整个过程称为一个生命周期,线程的生命周期包括五个阶段
(1)、新建状态:当一个线程Thread类的对象被创建后,被启动(star)之前,处于新建状态。
(2)、可运行状态(Runnable):线程启动之后,并不总是能够进入运行状态,它需要等待调度,获得CPU时间才能开始运行,在开始运行之前。
(3)、运行状态:线程的正常状态,即在cpu中执行run()方法的代码。
(4)、阻塞状态:由于某种原因,线程不能执行。
(5)、结束状态:线程正常执行完成,或线程中上,这时释放线程资源,结束线程执行。
6、多线程的同步、通信、与死锁
当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在同一时间仅被一个线程占有用,达到此目的的过程叫做同步(Synchronization)
保证同步的常用两各方式
(1)、
synchronized()
{
// 将需要同步的代码块包在括号中
}
(2)、在函数前面加上synchornied关键字来实现线程的同步 ,这时使用的同步监视器为this对象。
下面是一个售票系统的线程同步实现例子、
package itcast.thead.study;
public class TheadStu implements Runnable {
int tickets=100;//使用多个线程来卖这100张票
String str=new String("");
@Override
public void run() {
while(true)
{//使用synchronized方式来保证线程同步
synchronized (str) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(tickets>0){
System.out.println("this is selling number "+tickets-- +Thread.currentThread().getName());
}
}
this.sell();
}
}
public synchronized void sell()
{
if(tickets>0){
System.out.println("this is selling number "+tickets-- +Thread.currentThread().getName());
}
}
}
主函数类:
package itcast.thead.study;
public class TheadMain {
public static void main(String[] args) {
//Thread tt=new Thread(new TheadStu());
//tt.start();
TheadStu tt=new TheadStu();
new Thread(tt).start();//开启多个线程来售票
new Thread(tt).start();
new Thread(tt).start();
}
}
7、线程间的通信:
wait():告诉当前线程放弃监视器并进入睡眠状态直到其他线程进入同一监视并调用notfiy方法为止。
notify()唤醒同一对象监视器中调用wait的第一个线程。
notityAll() 唤醒所有同一对象监视器中调用wait的线程。