JAVA程序设计----多线程(上)

昨天外出了,没有更,老样子,思考小结。

1.Java为什么要引入线程机制,线程、程序、进程之间的关系是怎样的?


    线程可以彼此独立的执行,它是一种实现并发机制的有效手段,可以同时使用多个线程来完成不同的任务,并且一般用户在使用多线程时并不考虑底层处理的细节。


    进程(process)是程序的一次执行过程,或是正在运行的一个程序。线程是比进程更小的程序执行单位,一个进程可以启动多个线程同时运行,不同线程之间可以共享相同的内存区域和数据。



2.Java有哪几种创建线程的方式?它们的区别是什么?


    有三种方式,如下所示:


    (1)继承Thread类:编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。但线程类已经继承了Thread类,所以不能再继承其他父类。


    (2)实现Runnable接口:避免由于Java单继承带来的局限性。但编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

    
    (3)使用Callable接口和Future接口创建多线程:避免由于Java单继承带来的局限性,有返回值,可以抛出异常。但编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

 

3.什么是线程的生命周期?线程的生命周期中有哪几种状态?


    线程从新建到死亡称为线程的生命周期,线程有新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Terminated)五种状态

 

4.启动一个线程是用run()方法还是start()方法?


    启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

 

5.当一个线程进入一个对象的synchronized方法后,其它线程是否可进入此方法?


    不能,一个对象的一个synchronized方法只能由一个线程访问。

6.一个单CPU的机器,如何同时执行多个线程?


    从宏观上看,多线程的并发运行时各个线程轮流获得CPU的使用权,分别执行各自的任务。但在运行池中,会有多个处于就绪状态的线程在等待CPU,java虚拟机的一项任务就是负责线程的调度,即按照特定的机制为多个线程分配CPU使用权。调度模型分为分时调度模型和抢占式调度模型两种。前者是让所有线程轮流获得CPU使用权,平均分配每个线程占用CPU的时间片。抢占式调度模型是优先让可运行池中优先级高的线程占用CPU,若运行池中线程优先级相同,则随机选择一个线程使用CPU当它失去CPU使用权时,在随机选取一个线程获取CPU使用权。JAVA默认使用抢占式调度模型。

补充:

  • 线程的优先级:所有处于就绪状态的线程根据优先级存放在可运行池中,优先级低的线程运行机会较少,优先级高的线程运行机会较多,Thread类的setPriority(int newPriority)方法(可设置10种优先级)和getPriority()方法分别用于设置优先级和读取优先级。
  • 线程休眠:Thread类的静态方法sleep(),正在执行的线程调用sleep()方法可以进入阻塞状态,也叫线程休眠,在休眠时间内,即使系统中没有其他可执行的线程,该线程也不会获得执行的机会,当休眠时间结束才可以执行该线程。
  • 线程让步:yield()方法,它与sleep()方法相似,也可以让当前正在执行的线程暂停,但yield()方法不会使线程阻塞,只是将线程转换为就绪状态,也就是让当前线程暂停一下,线程调度器重新调度一下,有可能还会将暂停的程序调度出来继续执行,这就叫做线程让步。
  • 线程插队:join()方法。当某个线程执行中调用其它线程的join()方法时,此线程将被阻塞,直到被join()方法加入的线程执行完为止,称为线程插队。
  • 后台线程(守护线程):线程中有一种后台线程,为其他线程提供服务,JVM的垃圾回收线程就是典型的后台线程。如果所有的前台线程都死亡,后台线程会自动死亡。当整个虚拟机中只剩下后台线程,程序就没有继续运行的必要了,所以虚拟机也就退出了。若将一个线程设置为后台线程,则可以调用Thread类的setDaemon(boolean on)方法,将参数指定为true即可,Thread类还提供了一个isDarmon()方法,用于判断一个线程是否后台线程。

码起来:

1.利用多线程,同时输出10以内的奇数和偶数,以及当前运行的线程名称,输出数字完毕输出

end。

/**
 * 利用多线程,同时输出10以内的奇数和偶数,以及当前运行的线程名称,输出数字完毕输出end。
 * 1.synchronized(obj){
 *     //同步代码块
 * }
 * 2.public synchronized void  run() {
 *  //同步方法
 * }
 */
public class nineA {
    public static void main(String[] args) {
        MyRunnable1 myRunnable1 = new MyRunnable1();
        MyRunnable2 myRunnable2 = new MyRunnable2();
        new Thread(myRunnable1,"线程偶数:").start();
        new Thread(myRunnable2,"线程奇数:").start();
    }
}
//线程1   偶数
class MyRunnable1 implements Runnable{

    @Override
    public synchronized void  run() {
        for (int i = 0; i <= 10; i++) {
            if (i % 2 == 0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //currentThread()方法是在Thread类的静态方法,可以返回当前正在执行的线程对象的引用
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        System.out.println(Thread.currentThread().getName()+"end");
    }
}
//线程2    奇数
class MyRunnable2 implements Runnable{

    @Override
    public synchronized void run() {
        for (int i = 0; i <= 10; i++) {
            if (i % 2 != 0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //currentThread()方法是在Thread类的静态方法,可以返回当前正在执行的线程对象的引用
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        System.out.println(Thread.currentThread().getName()+"end");
    }
}

2.编写一个继承Thread类的方式实现多线程的程序,该类MyThread有两个属性:一个字符串WhoAmI代表线程名,
* 一个整数delay代表该线程随机要休眠的时间。利用有参的构造函数指定线程名称和休眠时间,休眠时间为随机数,
* 线程执行时,会显示线程名,和要休眠时间。最后,在main()方法中创建三个线程对象以展示执行情况。

import java.util.Random;

/**
 * 编写一个继承Thread类的方式实现多线程的程序,该类MyThread有两个属性:一个字符串WhoAmI代表线程名,
 * 一个整数delay代表该线程随机要休眠的时间。利用有参的构造函数指定线程名称和休眠时间,休眠时间为随机数,
 * 线程执行时,会显示线程名,和要休眠时间。最后,在main()方法中创建三个线程对象以展示执行情况。
 */
public class nineB {
    public static void main(String[] args) {
        Random random = new Random();
        MyThread myThread1 = new MyThread("线程1",((int) (random.nextDouble() * 10000.0)));
        MyThread myThread2 = new MyThread("线程1",((int) (random.nextDouble() * 10000.0)));
        MyThread myThread3 = new MyThread("线程1",((int) (random.nextDouble() * 10000.0)));
        myThread1.start();
        myThread2.start();
        myThread3.start();
    }
}

class MyThread extends Thread{
    private String WhoAmI;
    private int delay;

    public MyThread(String whoAmI, int delay) {
        WhoAmI = whoAmI;
        this.delay = delay;
    }

    @Override
    public synchronized void run() {
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+":"+delay);
    }
}

注:死锁问题:
* 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
* 注:在编写代码时要尽量避免死锁,采用专门的算法、原则,尽量减少同步资源的定义。

public class nineC {

    public static void main(String[] args) {
        TestDeadLock td1 = new TestDeadLock();
        TestDeadLock td2 = new TestDeadLock();
        td1.flag = 1;
        td2.flag = 0;
        new Thread(td1).start();
        new Thread(td2).start();
    }
}
class TestDeadLock implements Runnable{
    public int flag = 1;
    //static静态对象是类的所有对象共享的
//    private static Object o1 = new Object();
//    private static Object o2 = new Object();
    private Object o1 = new Object();
    private Object o2 = new Object();
    @Override
    public void run() {
        System.out.println("flag="+flag);
        if (flag == 1){
            synchronized (o1){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized(o2){
                    System.out.println("1");
                }
            }
        }
        if (flag == 0){
            synchronized (o2){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized(o1){
                    System.out.println("0");
                }
            }
        }
    }
}

 

你可能感兴趣的:(【JAVA】JAVA基础)