Java 多线程Thread start run

  • 进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该程序是一个执行路径,或者叫一个控制单元。
  • 线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。
  • 一个进程中至少有一个线程。
  • Java VM 启动的时候会有一个进程java.exe.
  • 该进程中至少一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。该线程称之为主线程。扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。

1.如何在自定义的代码中,自定义一个线程呢?通过对api的查找,java已经提供了对线程这类事物的描述。就Thread类。

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

步骤:
1.定义类集成Thread。
2.复写Thread类中的run方法。目的:将自定义的代码存储在run方法。让线程运行。
3.调用线程的start方法。该方法有两个作用:启动线程,调用run方法。

发现运行结果每一次都不同。因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。明确一点,在某一个时刻,只能有一个程序在执行。(多核除外)cpu在坐着快速的切换,以达到看上去是同时运行的效果。我们可以形象的把多线程的运行行为比作是在互相抢夺cpu的执行权。这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多长,cpu说了算。

为什么要覆盖run方法呢?

Thread类用于描述线程。该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。也就是说Thread类中的run方法,用于存储线程要运行的代码。

class Demo4 extends Thread
{
    public void run()
    {
        for (int x=0;x<6;x++)
        System.out.println("demo run-----"+x);
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        Demo4 d = new Demo4();//创建好一个线程。
        d.start();//开启线程并执行该线程的run方法。
        //d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
        for(int x=0;x<6;x++)
        System.out.println("Hello World!--" + x);
    }
}
//输出结果
Hello World!--0
demo run-----0
Hello World!--1
demo run-----1
Hello World!--2
demo run-----2
Hello World!--3
demo run-----3
Hello World!--4
demo run-----4
Hello World!--5
demo run-----5

class Demo4 extends Thread
{
    public void run()
    {
        for (int x=0;x<6;x++)
        System.out.println("demo run-----"+x);
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        Demo4 d = new Demo4();//创建好一个线程。
        //d.start();//开启线程并执行该线程的run方法。
        d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
        for(int x=0;x<6;x++)
        System.out.println("Hello World!--" + x);
    }
}
//输出结果
demo run-----0
demo run-----1
demo run-----2
demo run-----3
demo run-----4
demo run-----5
Hello World!--0
Hello World!--1
Hello World!--2
Hello World!--3
Hello World!--4
Hello World!--5

线程都有自己默认的名称,Thread-编号,该编号从0开始。static Thread currentThread():获取当前线程对象。getName():获取线程名称。设置线程名称:setName或者构造函数。

class Test1 extends Thread
{
    Test1(String name)
    {
        super(name);
    }
    public void run()
    {
        for (int x=0;x<6;x++)
        {
            System.out.println(Thread.currentThread().getName()+"run..."+x);
        }
    }
}
public class ThreadDemo0 {
    public static void main(String[] args) {
        Test1 t1 = new Test1("one---");
        Test1 t2 = new Test1("tw0+++");
        t1.start();
        t2.start();
        for (int i=0;i<6;i++)
            System.out.println("Hello world!"+i);
    }
}
//输出
Hello world!0
Hello world!1
Hello world!2
Hello world!3
Hello world!4
Hello world!5
one---run...0
one---run...1
one---run...2
tw0+++run...0
one---run...3
tw0+++run...1
one---run...4
tw0+++run...2
one---run...5
tw0+++run...3
tw0+++run...4
tw0+++run...5

创建线程的第二种方式:实现Runnable接口。

步骤:

  • 1.定义类实现Runnable接口
  • 2.覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
  • 3.通过Thread类建立线程对象。
  • 4.将Runable接口的子类对象座位实际参数传递给Thread类的构造函数。为什么要将Runnable接口的子类对象传递给Thread的构造函数。因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去执行指定对象的run方法。就必须明确该run方法所属对象。
  • 5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

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

实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。
两种方式区别:
继承Thread:线程代码存放Thread子类的run方法中。
实现Runnable:线程代码存在接口的子类的run方法中。

class Ticket implements Runnable
{
    private String name;
    Ticket(String name)
    {
        super();
    }
    private int sum = 100;
    public void run(){
        while (true)
        {
            if (sum>0)
                System.out.println(Thread.currentThread().getName()+"run---"+sum--);
        }
    }
}
public class ThreadDemo1 {
    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();
    }
}
//输出
Thread-0run---100
Thread-0run---96
Thread-2run---98
Thread-1run---99
Thread-3run---97
Thread-1run---93
Thread-2run---94
Thread-0run---95
Thread-2run---90
Thread-1run---91
Thread-3run---92
Thread-1run---87
Thread-2run---88
Thread-0run---89
Thread-0run---83
Thread-0run---82
Thread-0run---81
Thread-2run---84
Thread-1run---85
Thread-3run---86
Thread-3run---77
Thread-1run---78
Thread-1run---75
Thread-1run---74
Thread-1run---73
Thread-2run---79
Thread-0run---80
Thread-2run---71
Thread-1run---72
Thread-1run---68
Thread-1run---67
Thread-3run---76
Thread-1run---66
Thread-2run---69
Thread-0run---70
Thread-2run---63
Thread-1run---64
Thread-3run---65
Thread-1run---60
Thread-2run---61
Thread-0run---62
Thread-2run---57
Thread-1run---58
Thread-3run---59
Thread-1run---54
Thread-2run---55
Thread-0run---56
Thread-2run---51
Thread-1run---52
Thread-3run---53
Thread-1run---48
Thread-2run---49
Thread-0run---50
Thread-2run---45
Thread-1run---46
Thread-3run---47
Thread-1run---42
Thread-2run---43
Thread-0run---44
Thread-2run---39
Thread-1run---40
Thread-3run---41
Thread-1run---36
Thread-2run---37
Thread-0run---38
Thread-2run---33
Thread-1run---34
Thread-3run---35
Thread-1run---30
Thread-2run---31
Thread-0run---32
Thread-2run---27
Thread-1run---28
Thread-3run---29
Thread-1run---24
Thread-2run---25
Thread-0run---26
Thread-2run---21
Thread-1run---22
Thread-3run---23
Thread-1run---18
Thread-2run---19
Thread-0run---20
Thread-2run---15
Thread-1run---16
Thread-3run---17
Thread-1run---12
Thread-2run---13
Thread-0run---14
Thread-2run---9
Thread-1run---10
Thread-3run---11
Thread-1run---6
Thread-2run---7
Thread-0run---8
Thread-2run---3
Thread-1run---4
Thread-3run---5
Thread-2run---1
Thread-0run---2

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

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

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

Java对于多线程的安全问题提供了专业的解决方式。
就是同步代码块。
synchronized(对象)
{
需要被同步的代码
}

对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

火车上的卫生间---经典。

同步的前提:
1.必须要有两个或者两个以上的线程。
2.必须是多个线程使用同一个锁。

必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。

class Ticket implements Runnable
{
    private String name;

    Ticket(String name)
    {
        super();
    }

    private int sum = 100;

    public void run()
    {
        while (true)
        {
            synchronized (this)
            {
                if (sum > 0)
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//
//                    }
                    System.out.println(Thread.currentThread().getName() + "run---" + sum--);
            }
        }
     }
}

public class ThreadDemo1 {
    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();
    }
}

银行存钱的例子

银行有一个金库,有两个储户分别存300元,每次存100元,存3次。
目的:该程序是否有安全问题,如果有,如何解决?

如何找问题:
1.明确哪些代码是多线程运行代码。
2.明确共享数据。
3.明确多线程运行代码中哪些语句是操作共享数据的。

class Bank
{
    private int sum;
    public void add(int n)
    {
        try {
            Thread.sleep(10);
        }catch (InterruptedException e)
        {

        }
        sum = sum + n;
        System.out.println(Thread.currentThread().getName()+"sum="+sum);
    }
}
class Cus implements Runnable
{
    private Bank b = new Bank();
    public void run()
    {
        for (int x=0;x<3;x++)
        {
            b.add(100);
        }
    }
}
public class BankDemo {
    public static void main(String[] args) {
        Cus c = new Cus();
        Thread t1 = new Thread(c);
        Thread t2 = new Thread(c);
        t1.start();
        t2.start();
    }
}
//输出
Thread-0sum=200
Thread-1sum=200
Thread-1sum=400
Thread-0sum=400
Thread-1sum=500
Thread-0sum=600

添加同步锁
class Bank
{
    private int sum;
    public void add(int n)
    {
        synchronized (this)
        {
            try {
                Thread.sleep(10);
            }catch (InterruptedException e)
            {

            }
            sum = sum + n;
            System.out.println(Thread.currentThread().getName()+"sum="+sum);
        }
    }
}
class Cus implements Runnable
{
    private Bank b = new Bank();
    public void run()
    {
        for (int x=0;x<3;x++)
        {
            b.add(100);
        }
    }
}
public class BankDemo {
    public static void main(String[] args) {
        Cus c = new Cus();
        Thread t1 = new Thread(c);
        Thread t2 = new Thread(c);
        t1.start();
        t2.start();
    }
}
//输出
Thread-0sum=100
Thread-0sum=200
Thread-0sum=300
Thread-1sum=400
Thread-1sum=500
Thread-1sum=600

设置为同步函数
class Bank
{
    private int sum;
    public synchronized void add(int n)
    {
            try {
                Thread.sleep(10);
            }catch (InterruptedException e)
            {

            }
            sum = sum + n;
            System.out.println(Thread.currentThread().getName()+"sum="+sum);
    }
}
class Cus implements Runnable
{
    private Bank b = new Bank();
    public void run()
    {
        for (int x=0;x<3;x++)
        {
            b.add(100);
        }
    }
}
public class BankDemo {
    public static void main(String[] args) {
        Cus c = new Cus();
        Thread t1 = new Thread(c);
        Thread t2 = new Thread(c);
        t1.start();
        t2.start();
    }
}
//输出
Thread-0sum=100
Thread-0sum=200
Thread-0sum=300
Thread-1sum=400
Thread-1sum=500
Thread-1sum=600

同步函数用的是哪一个锁呢?函数需要被对象调用,那么函数都有一个所属对象引用,就是this。所以同步函数使用的锁是this。通过该程序进行验证。

  • 使用两个线程来买票。
  • 一个线程在同步代码块中。
  • 一个线程在同步函数中。
  • 都在执行买票动作。
class Ticket0 implements Runnable
{
    private  int tick = 100;
    boolean flag = true;
    Object obj = new Object();
    public void run()
    {
        if (flag)
        {
            while (true)
            {
                synchronized (obj)
                {
                    if (tick > 0) {
                        try { Thread.sleep(10); } catch (InterruptedException e) {}
                        System.out.println(Thread.currentThread().getName() + ".........sale" + tick--);
                    }
                }
            }
        }
        else
        while (true)
        {
            this.show();
        }
    }
    public synchronized void show()
    {
        if (tick > 0) {
            try { Thread.sleep(10); } catch (InterruptedException e) {}
            System.out.println(Thread.currentThread().getName() + ".....code" + tick--);
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        Ticket0 t = new Ticket0();

        Thread th0 = new Thread(t);
        Thread th1 = new Thread(t);

        System.out.println(Thread.currentThread().getName());
        th0.start();
        try { Thread.sleep(10); } catch (InterruptedException e) {}
        t.flag = false;
        th1.start();
    }
}
//输出
main
Thread-0.........sale100
Thread-1.....code99
Thread-0.........sale98
Thread-1.....code97
Thread-0.........sale96
Thread-1.....code95
Thread-0.........sale94
Thread-1.....code93
Thread-0.........sale92
Thread-1.....code91
Thread-0.........sale90
Thread-1.....code89
Thread-0.........sale88
Thread-1.....code87
Thread-0.........sale86
Thread-1.....code85
Thread-0.........sale84
Thread-1.....code83
Thread-0.........sale82
Thread-1.....code81
Thread-0.........sale80
Thread-1.....code79
Thread-0.........sale78
Thread-1.....code77
Thread-0.........sale76
Thread-1.....code75
Thread-0.........sale74
Thread-1.....code73
Thread-0.........sale72
Thread-1.....code71
Thread-0.........sale70
Thread-1.....code69
Thread-0.........sale68
Thread-1.....code67
Thread-0.........sale66
Thread-1.....code65
Thread-0.........sale64
Thread-1.....code63
Thread-0.........sale62
Thread-1.....code61
Thread-0.........sale60
Thread-1.....code59
Thread-0.........sale58
Thread-1.....code57
Thread-0.........sale56
Thread-1.....code55
Thread-0.........sale54
Thread-1.....code53
Thread-0.........sale52
Thread-1.....code51
Thread-0.........sale50
Thread-1.....code49
Thread-0.........sale48
Thread-1.....code47
Thread-0.........sale46
Thread-1.....code45
Thread-0.........sale44
Thread-1.....code43
Thread-0.........sale42
Thread-1.....code41
Thread-0.........sale40
Thread-1.....code39
Thread-0.........sale38
Thread-1.....code37
Thread-0.........sale36
Thread-1.....code35
Thread-0.........sale34
Thread-1.....code33
Thread-0.........sale32
Thread-1.....code31
Thread-0.........sale30
Thread-1.....code29
Thread-0.........sale28
Thread-1.....code27
Thread-0.........sale26
Thread-1.....code25
Thread-0.........sale24
Thread-1.....code23
Thread-0.........sale22
Thread-1.....code21
Thread-0.........sale20
Thread-1.....code19
Thread-0.........sale18
Thread-1.....code17
Thread-0.........sale16
Thread-1.....code15
Thread-0.........sale14
Thread-1.....code13
Thread-0.........sale12
Thread-1.....code11
Thread-0.........sale10
Thread-1.....code9
Thread-0.........sale8
Thread-1.....code7
Thread-0.........sale6
Thread-1.....code5
Thread-0.........sale4
Thread-1.....code3
Thread-0.........sale2
Thread-1.....code1
Thread-0.........sale0

出现0号票,表明不是同一个锁。

class Ticket0 implements Runnable
{
    private  int tick = 100;
    boolean flag = true;
    Object obj = new Object();
    public void run()
    {
        if (flag)
        {
            while (true)
            {
                synchronized (this)
                {
                    if (tick > 0) {
                        try { Thread.sleep(10); } catch (InterruptedException e) {}
                        System.out.println(Thread.currentThread().getName() + ".........sale" + tick--);
                    }
                }
            }
        }
        else
        while (true)
        {
            this.show();
        }
    }
    public synchronized void show()
    {
        if (tick > 0) {
            try { Thread.sleep(10); } catch (InterruptedException e) {}
            System.out.println(Thread.currentThread().getName() + ".....code" + tick--);
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        Ticket0 t = new Ticket0();

        Thread th0 = new Thread(t);
        Thread th1 = new Thread(t);

        System.out.println(Thread.currentThread().getName());
        th0.start();
        try { Thread.sleep(10); } catch (InterruptedException e) {}
        t.flag = false;
        th1.start();
    }
}
//输出正常:两个线程同步卖票
main
Thread-0.........sale100
Thread-0.........sale99
Thread-0.........sale98
Thread-0.........sale97
Thread-0.........sale96
Thread-0.........sale95
Thread-0.........sale94
Thread-0.........sale93
Thread-0.........sale92
Thread-0.........sale91
Thread-0.........sale90
Thread-0.........sale89
Thread-0.........sale88
Thread-0.........sale87
Thread-0.........sale86
Thread-0.........sale85
Thread-0.........sale84
Thread-0.........sale83
Thread-0.........sale82
Thread-0.........sale81
Thread-0.........sale80
Thread-0.........sale79
Thread-0.........sale78
Thread-0.........sale77
Thread-0.........sale76
Thread-0.........sale75
Thread-0.........sale74
Thread-0.........sale73
Thread-0.........sale72
Thread-0.........sale71
Thread-0.........sale70
Thread-0.........sale69
Thread-0.........sale68
Thread-0.........sale67
Thread-0.........sale66
Thread-0.........sale65
Thread-0.........sale64
Thread-0.........sale63
Thread-0.........sale62
Thread-0.........sale61
Thread-0.........sale60
Thread-0.........sale59
Thread-0.........sale58
Thread-0.........sale57
Thread-0.........sale56
Thread-0.........sale55
Thread-0.........sale54
Thread-0.........sale53
Thread-0.........sale52
Thread-0.........sale51
Thread-0.........sale50
Thread-0.........sale49
Thread-0.........sale48
Thread-0.........sale47
Thread-0.........sale46
Thread-0.........sale45
Thread-0.........sale44
Thread-0.........sale43
Thread-0.........sale42
Thread-0.........sale41
Thread-0.........sale40
Thread-0.........sale39
Thread-0.........sale38
Thread-0.........sale37
Thread-0.........sale36
Thread-0.........sale35
Thread-0.........sale34
Thread-0.........sale33
Thread-0.........sale32
Thread-0.........sale31
Thread-0.........sale30
Thread-0.........sale29
Thread-0.........sale28
Thread-0.........sale27
Thread-0.........sale26
Thread-0.........sale25
Thread-0.........sale24
Thread-0.........sale23
Thread-0.........sale22
Thread-0.........sale21
Thread-0.........sale20
Thread-1.....code19
Thread-1.....code18
Thread-1.....code17
Thread-1.....code16
Thread-1.....code15
Thread-1.....code14
Thread-1.....code13
Thread-1.....code12
Thread-1.....code11
Thread-1.....code10
Thread-1.....code9
Thread-1.....code8
Thread-1.....code7
Thread-1.....code6
Thread-1.....code5
Thread-1.....code4
Thread-1.....code3
Thread-1.....code2
Thread-1.....code1

如果同步函数被静态修饰后,使用的锁是什么呢?通过验证,发现不是this,因为静态方法中也不可以定义this。静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。类名.class 该对象的类型是Class。静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class。

class Ticket1 implements Runnable
{
    private  static int tick = 100;
    boolean flag = true;
    Object obj = new Object();
    public void run()
    {
        if (flag)
        {
            while (true)
            {
                synchronized (obj)
                {
                    if (tick > 0) {
                        try { Thread.sleep(10); } catch (InterruptedException e) {}
                        System.out.println(Thread.currentThread().getName() + ".........sale" + tick--);
                    }
                }
            }
        }
        else
            while (true)
            {
                show();
            }
    }
    public static synchronized void show()
    {
        if (tick > 0) {
            try { Thread.sleep(10); } catch (InterruptedException e) {}
            System.out.println(Thread.currentThread().getName() + ".....code" + tick--);
        }
    }
}
public class ThreadDemo3 {
    public static void main(String[] args) {
        Ticket1 t = new Ticket1();

        Thread th0 = new Thread(t);
        Thread th1 = new Thread(t);

        th0.start();
        try { Thread.sleep(10); } catch (InterruptedException e) {}
        t.flag = false;
        th1.start();
    }
}
//输出0号票,表明静态同步函数的锁不是obj,也不可能是this。
Thread-1.....code99
Thread-0.........sale100
Thread-1.....code98
Thread-0.........sale98
Thread-1.....code97
Thread-0.........sale97
Thread-1.....code96
Thread-0.........sale96
Thread-0.........sale95
Thread-1.....code95
Thread-0.........sale94
Thread-1.....code94
Thread-1.....code93
Thread-0.........sale93
Thread-1.....code92
Thread-0.........sale92
Thread-0.........sale91
Thread-1.....code91
Thread-1.....code90
Thread-0.........sale90
Thread-1.....code89
Thread-0.........sale89
Thread-1.....code88
Thread-0.........sale87
Thread-0.........sale85
Thread-1.....code86
Thread-0.........sale84
Thread-1.....code83
Thread-0.........sale82
Thread-1.....code82
Thread-0.........sale81
Thread-1.....code81
Thread-0.........sale80
Thread-1.....code80
Thread-0.........sale79
Thread-1.....code79
Thread-0.........sale78
Thread-1.....code78
Thread-0.........sale77
Thread-1.....code77
Thread-0.........sale76
Thread-1.....code76
Thread-1.....code74
Thread-0.........sale75
Thread-1.....code73
Thread-0.........sale72
Thread-1.....code71
Thread-0.........sale70
Thread-0.........sale69
Thread-1.....code69
Thread-1.....code68
Thread-0.........sale67
Thread-1.....code66
Thread-0.........sale65
Thread-1.....code64
Thread-0.........sale63
Thread-1.....code62
Thread-0.........sale61
Thread-1.....code60
Thread-0.........sale59
Thread-1.....code58
Thread-0.........sale58
Thread-1.....code57
Thread-0.........sale56
Thread-1.....code55
Thread-0.........sale54
Thread-0.........sale53
Thread-1.....code53
Thread-0.........sale52
Thread-1.....code52
Thread-1.....code51
Thread-0.........sale51
Thread-0.........sale50
Thread-1.....code50
Thread-0.........sale49
Thread-1.....code49
Thread-0.........sale48
Thread-1.....code47
Thread-1.....code46
Thread-0.........sale46
Thread-1.....code45
Thread-0.........sale44
Thread-0.........sale43
Thread-1.....code43
Thread-1.....code41
Thread-0.........sale42
Thread-1.....code40
Thread-0.........sale39
Thread-1.....code38
Thread-0.........sale37
Thread-1.....code36
Thread-0.........sale35
Thread-1.....code34
Thread-0.........sale33
Thread-1.....code32
Thread-0.........sale31
Thread-0.........sale30
Thread-1.....code29
Thread-0.........sale28
Thread-1.....code27
Thread-1.....code26
Thread-0.........sale25
Thread-0.........sale24
Thread-1.....code24
Thread-1.....code22
Thread-0.........sale23
Thread-1.....code21
Thread-0.........sale21
Thread-0.........sale20
Thread-1.....code19
Thread-0.........sale18
Thread-1.....code17
Thread-0.........sale16
Thread-1.....code15
Thread-1.....code13
Thread-0.........sale14
Thread-0.........sale12
Thread-1.....code12
Thread-0.........sale11
Thread-1.....code10
Thread-0.........sale9
Thread-1.....code8
Thread-0.........sale7
Thread-1.....code6
Thread-0.........sale5
Thread-1.....code4
Thread-0.........sale3
Thread-1.....code2
Thread-0.........sale1
Thread-1.....code0

class Ticket1 implements Runnable
{
    private  static int tick = 100;
    boolean flag = true;
    Object obj = new Object();
    public void run()
    {
        if (flag)
        {
            while (true)
            {
                synchronized (Ticket1.class)
                {
                    if (tick > 0) {
                        try { Thread.sleep(10); } catch (InterruptedException e) {}
                        System.out.println(Thread.currentThread().getName() + ".........sale" + tick--);
                    }
                }
            }
        }
        else
            while (true)
            {
                show();
            }
    }
    public static synchronized void show()
    {
        if (tick > 0) {
            try { Thread.sleep(10); } catch (InterruptedException e) {}
            System.out.println(Thread.currentThread().getName() + ".....code" + tick--);
        }
    }
}
public class ThreadDemo3 {
    public static void main(String[] args) {
        Ticket1 t = new Ticket1();

        Thread th0 = new Thread(t);
        Thread th1 = new Thread(t);

        th0.start();
        try { Thread.sleep(10); } catch (InterruptedException e) {}
        t.flag = false;
        th1.start();
    }
}
//输出正常
Thread-0.........sale100
Thread-0.........sale99
Thread-1.....code98
Thread-1.....code97
Thread-1.....code96
Thread-1.....code95
Thread-1.....code94
Thread-1.....code93
Thread-1.....code92
Thread-1.....code91
Thread-1.....code90
Thread-1.....code89
Thread-1.....code88
Thread-1.....code87
Thread-1.....code86
Thread-1.....code85
Thread-1.....code84
Thread-1.....code83
Thread-1.....code82
Thread-1.....code81
Thread-1.....code80
Thread-1.....code79
Thread-1.....code78
Thread-1.....code77
Thread-1.....code76
Thread-1.....code75
Thread-0.........sale74
Thread-0.........sale73
Thread-0.........sale72
Thread-0.........sale71
Thread-0.........sale70
Thread-0.........sale69
Thread-0.........sale68
Thread-0.........sale67
Thread-0.........sale66
Thread-0.........sale65
Thread-0.........sale64
Thread-0.........sale63
Thread-1.....code62
Thread-1.....code61
Thread-1.....code60
Thread-1.....code59
Thread-1.....code58
Thread-1.....code57
Thread-1.....code56
Thread-1.....code55
Thread-1.....code54
Thread-1.....code53
Thread-0.........sale52
Thread-0.........sale51
Thread-0.........sale50
Thread-0.........sale49
Thread-0.........sale48
Thread-1.....code47
Thread-1.....code46
Thread-1.....code45
Thread-1.....code44
Thread-1.....code43
Thread-1.....code42
Thread-1.....code41
Thread-1.....code40
Thread-0.........sale39
Thread-0.........sale38
Thread-0.........sale37
Thread-0.........sale36
Thread-1.....code35
Thread-1.....code34
Thread-1.....code33
Thread-1.....code32
Thread-1.....code31
Thread-1.....code30
Thread-1.....code29
Thread-1.....code28
Thread-1.....code27
Thread-1.....code26
Thread-1.....code25
Thread-1.....code24
Thread-1.....code23
Thread-1.....code22
Thread-1.....code21
Thread-1.....code20
Thread-1.....code19
Thread-1.....code18
Thread-1.....code17
Thread-1.....code16
Thread-1.....code15
Thread-1.....code14
Thread-1.....code13
Thread-1.....code12
Thread-1.....code11
Thread-1.....code10
Thread-1.....code9
Thread-1.....code8
Thread-1.....code7
Thread-1.....code6
Thread-1.....code5
Thread-1.....code4
Thread-1.....code3
Thread-1.....code2
Thread-1.....code1

单例

饿汉式

class Single
{
   private static Singele s = new Single();
   private Single(){};
   private static Single getInstance()
   {
       returen s;
   }
}

懒汉式

class Single
{
   private static Single s = null;
   private Single(){};
   private static Single getInstance()
   {
        if(s == null)
        {
           synchronized(Single.class)
           {
              if(s == null)
                  s = new Single();
           }
        }
        return s;
   }
}

死锁

class Test2 implements Runnable
{
    private boolean flag;
    Test2(Boolean flag)
    {
       this.flag = flag;
    }
    public void run()
    {
        if (flag)
        {
            synchronized (MyLock.locka)
            {
                System.out.println("if locka");
                synchronized (MyLock.lockb)
                {
                    System.out.println("if lockb");
                }
            }
        }
        else
        {
            synchronized (MyLock.lockb)
            {
                System.out.println("else lockb");
                synchronized (MyLock.locka)
                {
                    System.out.println("else locka");
                }
            }
        }
    }
}
class MyLock
{
    static Object locka = new Object();
    static Object lockb = new Object();
}
public class DeadLockDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Test2(true));
        Thread t2 = new Thread(new Test2(false));
        t1.start();
        t2.start();
    }
}
//输出:程序无法结束,光标一直闪。
2.gif

你可能感兴趣的:(Java 多线程Thread start run)