一,概述
1, 进程
是一个正在执行的程序。
每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
2,线程
就是进程中的一个独立的控制单元。线程在控制着进程的执行。只要进程中有一个线程在执行,进程就不会结束。
一个进程中至少有一个线程。
3,多线程存在的意义
多线程的出现能让程序产生同时运行效果。可以提高程序执行效率。
二,创建线程的方式
方式一:继承步骤:
a,定义类继承Thread。
b,复写Thread中的run方法。
目的:将自定义代码存储在run方法中,让线程运行。
c,创建定义类的实例对象。相当于创建一个线程。
d,用该对象调用线程的start方法。该方法的作用是:启动线程,调用run方法。
注:如果对象直接调用run方法,等同于只有一个线程在执行,自定义的线程并没有启动。
public class thread_text {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(new lineone()).start();//创建线程并启动
new Thread(new linetwo()).start();
}
public synchronized void print(Object obj){
System.out.println(obj);
}
}
class lineone implements Runnable
{
public void run()//覆盖run方法,方法内为线程要执行的代码
{
long begin=System.currentTimeMillis();
for(int k=0;k<100;k++){
System.out.println("*********"+k);
}
long end=System.currentTimeMillis();
System.out.println(end-begin);
}
}
class linetwo implements Runnable{
public void run(){
long begin=System.currentTimeMillis();
for(int k=0;k<100;k++){
System.out.println("---------"+k);
}
long end=System.currentTimeMillis();
System.out.println(end-begin);
}
}
步骤:
a,定义类实现Runnable的接口。
b,覆盖Runnable接口中的run方法。目的也是为了将线程要运行的代码存放在该run方法中。
c,通过Thread类创建线程对象。
d,将Runnable接口的子类对象作为实参传递给Thread类的构造方法。
示例:
public class threaddemo {
/**
* @param args
*/
public static void main(String[] args) {
new Thread(new newline()).start();//Runnable接口子类对象作为参数传递给Thread类构造函数并调用start方法启动线程。
}
}
class newline implements Runnable//实现Runnable接口
{
public void run()//覆盖接口run方法 放入要被线程执行的代码。
{
int x=0;
while(x<10)
{
System.out.println("我是新线程");
x++;
}
}
}
三,两种方式的区别与线程的状态
继承Thread:线程代码存放在Thread子类run方法中。
实现Runnable:线程代码存放在接口子类run方法中。
几种状态:
被创建:等待启动,调用start启动。
运行状态:具有执行资格和执行权。
临时状态(阻塞):有执行资格,但是没有执行权。
冻结状态:遇到sleep(time)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。
消忙状态:stop()方法,或者run方法结束。
四,线程的安全
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
a,同步代码块
用法:
synchronized(对象)
{需要被同步的代码}
b,同步函数
格式:
在函数上加上synchronized修饰符即可。
同步的前提
a,必须要有两个或者两个以上的线程。
b,必须是多个线程使用同一个锁。
3,同步的利弊
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
五,死锁
public class threaddemo3//死锁练习。
{
public static void main(String[] args) {
new Thread(new Test(true)).start();
new Thread(new Test(false)).start();
}
}
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag=flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(ownlock.locka)
{ System.out.println("if heima a");
synchronized(ownlock.lockb)
{
System.out.println("if heima b");
}
}
}
}
else
{
while(true)
{
synchronized(ownlock.lockb)
{ System.out.println("else heima b");
synchronized(ownlock.locka)
{
System.out.println("else heima a");
}
}
}
}
}
}
class ownlock// 此类用于提供锁 。
{
static Object locka = new Object();
static Object lockb = new Object();
}
六,线程间通信
public class thread_text2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
resource a=new resource();
new Thread(new threadset(a)).start();//启动线程
new Thread(new threadget(a)).start();
}
}
class threadget implements Runnable//获取资源线程
{
resource r=null;
threadget(resource b)//自定义构造方法,接受资源对象
{
this.r=b;
}
public void run(){
while(true){
r.getOutput();
}
}
}
class threadset implements Runnable//存储资源线程
{
resource r=null;
threadset(resource b){
this.r=b;
}
public void run(){
while(true){
r.setInPut("异界的旅行者","man",22);
}
}
}
class resource //资源
{
private String name;
private String sex;
private int age;
boolean f=false;
public String toString()//重写toString方法
{
return ("name:"+name+" sex:"+sex+" age:"+Integer.toString(age));
}
public synchronized void setInPut(String str,String sex,int age)
{
if(f){
try{wait();}catch(Exception e){}
}
this.name=str;
this.sex=sex;
this.age=age;
f=true;
System.out.println("存"+toString());
notify();//唤醒
}
public synchronized void getOutput()
{
if(!f){
try{wait();}catch(Exception e){}
}
System.out.println("取"+toString());
f=false;
notify();
}
}
JDK1.5中提供了多线程升级解决方案。
将同步synchronized替换成显示的Lock操作。将Object中wait,notify,notifyAll,替换成了Condition对象。该Condition对象可以通过Lock锁进行获取,并支持多个相关的Condition对象。