黑马程序员_java多线程(1)

来源:互联网 发布:倩女手游 mac 编辑:程序博客网 时间:2024/05/02 04:32

----------- android培训java培训java学习型技术博客、期待与您交流! ------------

多线程

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

线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行.

一个进程中至少有一个线程.

Java VM  启动的时候会有一个进程,java.exe.该进程中至少一个线程负责java程序的执行.而且这个线程运行的代码存在于main方法中.该线程称之为主线程.

扩展知识:Java VM 启动时有两个线程,一个是主线程,另一个是垃圾回收机制线程.(例如,下载程序是多线程.)

意义:多线程的出现使多个程序同时执行,提高效率.

如何在自定义的代码中自定义一个线程?

创建线程的第一种方式:

继承Thread.

复写Thread类中的run方法.

目的:将自定义代码存储在run方法中,让线程运行.

调用线程的start方法.该方法的两个作用:

1启动线程

2调用run方法

例题

class Demo extends Thread{

public void run(){

 System.out.println(Demo run)

}

}

Class ThreadDemo{

Public static void main(string args[]){

Demo D = new Demo();

创建一个线程

D.start();

}

}

与调用run方法的区别?

class Demo extends Thread{

public void run(){

for(int x = 0; x< 60;x++)

 System.out.println(Demo run” + x)

}

}

Class ThreadDemo{

Public static void main(string args[]){

Demo D = new Demo();

D.start();

For(int x = 0; x < 60; x++)

System.out.println(Hello” + x)

}

}

Main执行hello,D.start执行Demo.形成了多线程.ThreadDemo中有两个执行路径,在真实情况下是绝对不可能同时执行的(除非双核即双CPU).因为CPU切换的极快.

发现运行结果每一次都不同,因为多个线程都获取CPU的执行权,CPU执行的谁,谁就运行谁.其实这就是多线程的随机性.

为什么要覆盖run方法呢?

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

Class ThreadDemo{

Public static void main(string args[]){

Thread t  =  new Thread();

          T.start();

}

}

运行结果:没有任何结果.因为run()()中没有任何东西.

Class ThreadDemo{

Public static void main(string args[]){

Demo D = new Demo();

D.start();

开启线程并执行线程的run方法.

D.run();

仅仅是对象调用.

 

}

}

 

例题:创建两个线程与主线程交替运行?

class Demo extends Thread{

private String name;

Demo(String name){

this.name = name;

public void run(){

for(int x = 0; x< 60;x++){

 System.out.println(name + Demo run” + x)

}

}

}

Class ThreadDemo{

Public static void main(string args[]){

Demo D = new Demo(one);

Demo D1 = new Demo(two);

D.start();

D1.start();

for(int x = 0; x< 60;x++)

 System.out.println(Demo run” + x)

   }

}

获取多线程的对象及其名称.(getName()或者Thread.currdntThread())

class Demo extends Thread{

private String name;

Demo(String name){

this.name = name;

public void run(){

for(int x = 0; x< 60;x++){

 System.out.println(this.getName() + Demo run” + x)

}

}

}

Class ThreadDemo{

Public static void main(string args[]){

Demo D = new Demo(one);

Demo D1 = new Demo(two);

D.start();

D1.start();

for(int x = 0; x< 60;x++)

 System.out.println(Demo run” + x)

   }

}

线程均有自己的默认名称.Thread-编号,该编号从零开始.

Thread.currdntThread():获取当前线程对象.

getName():获取线程名称.

设置线程名称:setName()或构造函数

例题:买票程序;

注意:假设5个窗口.

1.5个窗口必须同时运行.

2.不能卖重复的票

class Ticket extends Thread

{

private static int tick = 100;

public void run(){

While(true){

if(tick > 0){

System.out.println(Tread.currentThread().getName()+..sale+tick--);

            }

         }

     }

 }

class TicketDemo{

Public static void main(string args[]){

Ticket t1 = new Ticket();

Ticket t2 = new Ticket();

Ticket t3 = new Ticket();

Ticket t4 = new Ticket();

Ticket t5 = new Ticket();

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

 

}

}

若不用静态,如何解决.(Runnable接口)

class Ticket implements Runnable

{

private int tick = 100;

public void run(){

While(true){

if(tick > 0){

System.out.println(Tread.currentThread().getName()+..sale+tick--);

            }

         }

     }

 }

class TicketDemo{

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);

Thread t5 = new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

 

}

}

Runnable接口是线程创建的第二种方式.

步骤:

1定义类实现Runnable接口.

覆盖Runnable接口中的run方法.

讲线程要运行的代码存放在该run方法中.

3通过Thread类建立线程对象.

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

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

因为自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run方法.就必须明确该run方法所属对象.

调用Thread类的start地 方法开启线程并调用Runnable接口子类的run方法.

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

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

实现Runnable:线程代码存在接口的子类的run方法中.

实现方式优势:避免了单继承的局限性.在定义线程时,建立使用实现方式.

多线程的安全问题.

class Ticket implements Runnable

{

        private int tick = 100;

Object obj = new Object();

 public void run(obj){

While(true){

if(tick > 0){

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

System.out.println(Tread.currentThread().getName()+..sale+tick--);

            }

         }

     }

 }

class TicketDemo{

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);

Thread t5 = new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

 

}

}

发现代码打印出 0, -1 ,-2等错票.

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

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

Java对于多线程的安全问题提供的解决办法是synchronized(同步代码块)

Synchronized(对象){
需要被同步的代码

}

class Ticket implements Runnable

{

        private int tick = 100;

 public void run(){

While(true){

Synchronized(对象){
    if(tick > 0){

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

System.out.println(Tread.currentThread().getName()+..sale+tick--);

            }

         }

     }

 }

}

class TicketDemo{

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);

Thread t5 = new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start(); 

}

}

同步时明确3

1,明确哪些代码是多线程运行代码.

2,明确共享数据

3明确多线程运行代码中哪些语句是操作共享数据的.

同步的两种方式:同步代码块.同步函数(public synchronized void 函数名())

多线程同步代码的锁是this.

如果同步函数被静态修饰后,使用的是什么锁?

静态进内存后,内存中没有本类对象.但是一旦有该类对应到字节码文件对象.类名.class  

该对象的类型是Class

静态的同步方法:使用的锁是该方法所在类的字节码文件对象.也就是类名.class

多线程---死锁

同步中嵌套同步

class Test{

Private boolean flag;

Tead(boolean flag){

this.flag = flag }

if (flag){

synchronized(MyLick.locka){

System.out.println(if  locka)

synchronized(MyLick.lockb){

System.out.println(if  lockb)

     }

   }

 } 

else{ 

synchronized(MyLick.lockb) {

System.out.println(else  lockb)

synchronized(MyLick.locka){

System.out.println(else  locka)

}

}
}
}

}

class MyLick {

static object locka = new object();

static object lockb = new object();

  }

class  DeadLockTest{

  public static void main (String args[]){

Thread t1 = new Thread (new Test(true));

Thread t2 = new Thread (new Test(false));

t1.start();

T2.start();

}

}

 

0 0
原创粉丝点击