您的位置:首页 > 职场人生

黑马程序员《多线程(一创建线程的两种方式)》

2015-03-27 22:42 465 查看

---------------------------ASP.Net+Android+IOS开发、java培训、期待与您交流!
---------------------------------

一、线程概念

1、什么是线程?什么是进程?

进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。

线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行,一个进程中至少有一个线程。

java vm 启动时会有一个进程java.exe,该进程中至少一个线程负责java程序的执行。

而且这个线程运行的代码存在于main方法中,该线程称之为主线程。

扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。

2、如何在一个自定义的代码中,自定义一个线程呢?

通过api的查找,java已经提供了对线程这类事物的描述,就Thread类。

创建线程的第一种方式:继承Thread类。

步骤:

1、定义类继承Thread.

2、复写Thread类中run方法。

3,调用线程的start方法。

代码:创建线程并启动

PrimeThread p = new PrimeThread(143);

p.start();

实例:class PrimeThread extends Thread

{ long minPrime;

PrimeThread(long minPrime) {

this.minPrime = minPrime;

} public void run()

{ // compute primes larger than minPrime

. . .}

}

创建线程的第二种方式:

代码:创建并启动一个线程

PrimeRun p = new PrimeRun(143);

new Thread(p).start();

代码:实例Runnable接口

class PrimeRun implements Runnable {

long minPrime;

PrimeRun(long minPrime) {

this.minPrime = minPrime; }

public void run() { // compute primes larger than minPrime

. . . } }

该方法两个作用,启动线程,调用run方法。发现运行结果每一次都不同。因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。

明确一点,在某一时刻,只能有一个程序在运行。(多核除外)

cpu在做着快速切换,已达到看上去是同时运行的效果。

互相抢夺cpu的执行权,多线程的特点:随机性。

3、 为什么要覆盖run方法呢?

下面以一个例子来演示这种使用线程的方法,首先创建一个Thread类的子类,并覆盖Thread类中的run()方法。
package com.javaeasy.usethread; // 程序所在的包

public class MyThread extends Thread { //

MyThread类继承自Thread类

public void run() { //

覆盖Thread类中的run()方法

System.out.println("这是在另一个线程中执行的代码。");

//

向控制台输出一行字

} //

run()方法结束

}

上面的类很简单。首先需要注意的就是MyThread类继承自Thread类,然后是MyThread类覆盖了Thread类中的run()方法。这样才能够让线程在启动后(调用start()方法后)执行到想让线程执行的内容。好,下面是一个使用MyThread类的例程。
package com.javaeasy.usethread; // 程序所在的包

public class UseMyThread { // 例程类

public static void main(String[] args) { // main()方法

MyThread thread = new MyThread(); //

创建一个Thread类的实例

thread.start(); //

启动一个新的线程

}

}

二、创建线程第二种方式:实现Runable接口

(1)实现Runnable接口

步骤:1、定义类实现Runnable接口

2、覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。

3、通过Thread类建立线程对象。

4、将Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。

1)为什么要将Runnable接口的子类对象传递给Thread的构造函数。

答:因为自定义的run方法所属的分对象是Runnable接口的子类对象。

所以要让线程去执行指定对象的run方法。就必须明确该run方法所属对象。

5、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

(2)实现方式和继承方式有什么区别呢?

实现方式好处:避免了单继承的局限性。

在定义线程时,建立使用实现方式。

两种方式区别:

继承Thread:线程代码存放Thread子类run方法中。

实现Runnable,线程代码存在接口的子类的run方法。

(3)多线程的运行出现了安全问题。

问题的原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。

解决办法:

对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。

Java对于多线程的安全问题提供了专业的解决方式。

就是同步代码块。

synchronized(对象)

{

需要被同步的代码

}

对象如同锁。持有锁的线程可以在同步中执行。

没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

(4)代码

class Ticket implements Runnable//extends Thread

{

private int tick = 1000;

Object obj = new Object();

public void run()

{

while(true)

{

synchronized(obj)

{

if(tick>0)

{

//try{Thread.sleep(10);}catch(Exception e){}

System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);

}

}

}

}

}

class TicketDemo2

{

public static void main(String[] args)

{

Ticket t = new Ticket();

Thread t1 = new Thread(t);//创建了一个线程;

Thread t2 = new Thread(t);//创建了一个线程;

Thread t3 = new Thread(t);//创建了一个线程;

Thread t4 = new Thread(t);//创建了一个线程;

t1.start();

t2.start();

t3.start();

t4.start();

}

}

---------------------------ASP.Net+Android+IOS开发、java培训、期待与您交流!
---------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: