看了一上午的java多线程的知识,了解的不是很多,简单的记录一下上午学习的知识。

多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。线程是在同一时间需要完成多项任务的时候被实现的。 使用线程的好处有以下几点: ·使用线程可以把占据长时间的程序中的任务放到后台去处理 ·程序的运行速度可能加快 ·在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。 最关键的一点,多线程可以让同一个程序的不同部分并发执行。

1:线程有两种实现方式     

(1)继承Thread类  (2)实现Runnable接口 

例子   

/**

 * @author Rollen-Holt 继承Thread类,直接调用run方法

 * */

class hello extends Thread {

 

    public hello() {

 

    }

 

    public hello(String name) {

        this.name = name;

    }

 

    public void run() {

        for (int i = 0; i < 5; i++) {

            System.out.println(name + "运行     " + i);

        }

    }

 

    public static void main(String[] args) {

        hello h1=new hello("A");

        hello h2=new hello("B");

        h1.run();

        h2.run();

    }

 

    private String name;

}

【运行结果】:

A运行     0

A运行     1

A运行     2

A运行     3

A运行     4

B运行     0

B运行     1

B运行     2

B运行     3

B运行     4

我们会发现这些都是顺序执行的,说明我们的调用方法不对,应该调用的是start()方法。


当我们改为start()方法时 



然后运行程序,输出的可能的结果如下:

A运行     0

B运行     0

B运行     1

B运行     2

B运行     3

B运行     4

A运行     1

A运行     2

A运行     3

A运行     4

因为start()函数需要调用系统的本地操作的函数,需要用到系统的资源,所以每一次结结果都是不一样的。

(2)通过实现Runnable接口

public class hello1 implements Runnable{//继承Runnsble接口就必须实现run()函数

	public hello1()
	{
		
	}
	public hello1(String name)
	{
		this.name=name;
	}
	private String name;
	public void run()
	{
		for(int i=0;i<5;i++)
			System.out.println(name+"运行      "+i);
	}
	public static void main(String[] args){
		hello1 h1=new hello1();//Runnable接口中不存在start()函数,把实现了接口的对象当做参数传进Thread中
		Thread demo=new Thread(h1);
		hello1 h2=new hello1();//如果不提供名字的话,系统会自动提示名字
		Thread demo1=new Thread(h2);
		demo.start();
		demo1.start();
	}

 


Thread和Runnable的区别:

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

 

2:线程的生命周期

新建(new Thread)当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread  t1=new Thread();

就绪(runnable)线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

运行(running)线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复

3:操作线程的方法

线程的休眠

在程序中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。

线程的中断

一个线程可以被另一个线程中断其操作的状态,使用interrupt()方法。

线程的礼让。

在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。

 

4:线程的同步

class hello implements Runnable {

    public void run() {

        for(int i=0;i<10;++i){

            if(count>0){

                try{

                    Thread.sleep(1000);

                }catch(InterruptedException e){

                    e.printStackTrace();

                }

                System.out.println(count--);

            }

        }

    }

 

    public static void main(String[] args) {

        hello he=new hello();

        Thread h1=new Thread(he);

        Thread h2=new Thread(he);

        Thread h3=new Thread(he);

        h1.start();

        h2.start();

        h3.start();

    }

    private int count=5;

}

 

【运行结果】:

5

4

3

2

1

0

-1

这里出现了-1,显然这个是错的。,应该票数不能为负值。

如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,

其他的线程必须等到这个线程结束之后才能继续执行。

【使用线程同步解决问题】

采用同步的话,可以使用同步代码块和同步方法两种来完成。

【同步代码块】:

语法格式:

synchronized(同步对象){

//需要同步的代码

}

【同步方法】

也可以采用同步方法。

语法格式为synchronized 方法返回类型方法名(参数列表){

    // 其他代码

}