一、线程和进行:

1进程的概念

进程就是正在执行的程序,一个进程通常就是一个正在执行的应用程序。从Windows角度讲,进程是含有内存和资源并安置线程的地方。

②准确的讲,进程就是一个可执行的程序一次运行的过程,它是系统进行资源分配和调度的一个独立单位。

2.线程的概念

线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。

3.进程和线程的联系与区别

①一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个主线程。

②系统资源分配给进程,同一进程的所有线程共享该进程的所有资源。

③线程是指进程内的一个执行单元,也是进程内的可调度实体。

4多线程的概念

多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

5多线程的好处

Java支持编写多线程的程序;

②多线程最大好处在于可以同时并发执行多个任务;

③多线程可以最大限度地减低CPU的闲置时间,从而提高CPU的利用率。

6多线程的不利方面

①线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;

②多线程需要协调和管理,所以需要CPU时间跟踪线程;

③线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;

④线程太多会导致控制太复杂,最终可能造成很多Bug

7 JAVA中主线程

①任何一个Java程序启动时,一个线程立刻运行,它执行main方法,这个线程称为程序的主线程;

也就是说,任何Java程序都至少有一个线程,即主线程;

②主线程的特殊之处在于:

③它是产生其它线程子线程的线程;

④通常它必须最后结束,因为它要执行其它子线程的关闭工作。

二、Java创建线程的两种方法

继承Thread类的方式

实现Runnable接口的方式

1Java中要实现线程,最简单的方式就是扩展Thread类,重写其中的run方法,方法原型如下:

public void run()

Thread类中的run方法本身并不执行任何操作,如果我们重写了run方法,当线程启动时,它将执行run方法。

Thread类也实现了Runnable接口。

通过继承Thread

定义:

public class MyThread extends Thread {

public void run() {

……

}

}

调用:

MyThread thread = new MyThread();

thread.start();

②自定义线程 – 实现Runnable接口

java.lang.Runnable接口中仅仅只有一个抽象方法:

public void run()

也可以通过实现Runnable接口的方式来实现线程,只需要实现其中的run方法即可;

Runnable接口的存在主要是为了解决Java中不允许多继承的问题。

③通过实现Runnable接口

定义:

public class MyThread implements Runnable{

@Override

public void run() {

……

}

}

调用:

MyThread r = new MyThread();

//创建一个线程作为外壳,将r包起来,

Thread thread = new Thread(r);

thread.start();

三、使用匿名内部类创建线程

1匿名内部类的概念

①内部类是指在一个外部类的内部再定义一个类。

②匿名内部类也就是没有名字的内部类。

③正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。

④使用匿名内部类的前提条件是必须继承一个父类或实现一个接口。

2使用匿名内部类的注意点

①继承抽象类的匿名内部类

abstract class Person {

    public abstract void eat();

}

 

public class Demo {

    public static void main(String[] args) {

        Person p = new Person() {

            public void eat() {

                System.out.println("eat something");

            }

        };

        p.eat();

    }

}

②实现接口的匿名内部类

interface Person {

    public void eat();

}

 

public class Demo {

    public static void main(String[] args) {

        Person p = new Person() {

            public void eat() {

                System.out.println("eat something");

            }

        };

        p.eat();

    }

}

③匿名内部类不能有构造方法;

④匿名内部类不能定义任何静态成员、方法和类;

⑤匿名内部类不能是publicprotectedprivatestatic

⑥只能创建匿名内部类的一个实例;

⑦一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类;

⑧因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效;

⑨在匿名类中用this时,这个this指的是匿名类本身。如果我们要使用外部类的方法和变量的话,应该加上外部类的类名。

3使用匿名内部类创建线程

①匿名内部类常用在多线程的实现上,因为要实现多线程必须继承Thread类或是实现Runnable接口。

Thread类的匿名内部类实现

public class ThreadDemo {

public static void main(String[] args) {

Thread thread = new Thread() {

public void run() {

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

           System.out.print(i + " ");

}

}

};

thread.start();

}

}

等价的非匿名内部类实现

class MyThread extends Thread {

public void run() {

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

System.out.print(i + " ");

}

}

}

public class ThreadDemo {

public static void main(String[] args) {

MyThread thread = new MyThread();

thread.start();

}

}

Runnable接口的匿名内部类实现

public class RunnableDemo {

public static void main(String[] args) {

Runnable r = new Runnable() {

public void run() {

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

          System.out.print(i + " ");

}

}

};

Thread thread = new Thread(r);

thread.start();

}

}

等价的非匿名内部类实现

class MyThread implements Runnable {

public void run() {

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

System.out.print(i + " ");

}

}

}

 

public class RunnableDemo {

public static void main(String[] args) {

MyThread r = new MyThread();

Thread thread = new Thread(r);

thread.start();

}

}

四、Thread类中常用方法

1 Thread类的常用静态方法

      

      

static Thread currentThread()

返回对当前正在执行的线程对象的引用

static void sleep(long millis)

throws InterruptedException

让当前正在执行的线程休眠(暂停执行),休眠时间由millis(毫秒)指定

static void sleep(long millis, int nanos)

throws InterruptedException

让当前正在执行的线程休眠,休眠时间由millis(毫秒)和nanos(纳秒)指定

static void yield()

暂停当前正在执行的线程,转而执行其它的线程

static boolean interrupted()

判断当前线程是否已经中断

java.lang.Thread类用于创建和操作线程,其中包括几个很重要的静态方法,用于控制当前线程:

 

2 Thread类的构造方法

   

      

Thread()

创建一个新的线程

Thread(String name)

创建一个指定名称的线程

Thread(Runnable target)

利用Runnable对象创建一个线程,启动时将执行该对象的run方法

Thread(Runnable target, String name)

利用Runnable对象创建一个线程,并指定该线程的名称

Thread类共提供8种构造方法重载,以下是常用的几种:

 

 

3线程优先级

①事实上,计算机只有一个CPU,各个线程轮流获得CPU的使用权,才能执行任务;

②优先级较高的线程有更多获得CPU的机会,反之亦然;

③优先级用整数表示,取值范围是1~10,一般情况下,线程的默认优先级都是5,④但是也可以通过setPrioritygetPriority方法来设置或返回优先级;

 

Thread类有如下3个静态常量来表示优先级

MAX_PRIORITY:取值为10,表示最高优先级。

MIN_PRIORITY:取值为1,表示最底优先级。

NORM_PRIORITY:取值为5,表示默认的优先级。

4 sleep用法

Thread.sleep(long millis)Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。

②线程睡眠的原因:线程执行太快,或者需要强制进入下一轮睡眠的实现:调用静态方法。

try {

Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();  
}

5 睡眠的位置

①为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠。

②线程睡眠是帮助所有线程获得运行机会的最好方法。

③线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。

sleep()是静态方法,只能控制当前正在运行的线程。

6 yield的用法

Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程,让相同优先级的线程之间能适当的轮转执行。

yield() 做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

③结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。

7 join的用法

①常用于主线程需要用到子线程执行完后的结果,即主线程需要等待子线程执行完成后再结束。

例:创建并启动线程t,加入到当前运行的线程中

MyThread t = new MyThread();
t.start();
t.join();

      

      

final void setDaemon(boolean on)

将该线程设置为后台线程

final boolean isDaemon()

判断该线程是否为后台线程

8与后台线程相关的方法

 

 

要将某个线程设置为后台线程的话,必须在它启动之前调用setDeamon方法;

默认情况下,由前台线程创建的线程仍是前台线程,由后台线程创建的线程仍是后台线程。