黑马程序员 Java基础 多线程

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1多线程与进程

 

以扫雷游戏说明一个进程中的多个线程:

一个计时器,一个点点点

 

多线程的目的是为了提高应用程序的使用率。

(程序的线程越多,抢到的几率就越高)

 

Java程序的运行原理及JVM的启动是多线程的吗?

A:Java命令去启动JVMJVM会启动一个进程,该进程会启动一个主线程。然后主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。在此之前的所有程序都是单线程的。

B:JVM的启动是多线程的,因为它最低有两个线程启动了,主线程和垃圾回收线程。

 

2多线程的实现方法

方法一:继承Thread类。

 

   A:自定义类MyThread继承Thread类。

   B:MyThread类里面重写run()?

   为什么是run()方法呢?

   C:创建对象

   D:启动线程

 

该类要重写run()方法,为什么呢?

  不是类中的所有代码都需要被线程执行的。

  而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。

 

run()start()的区别?

run():仅仅是封装被线程执行的代码,直接调用是普通方法

start():首先启动了线程,然后再由jvm去调用该线程的run()方法。

 

  public final String getName():获取线程的名称。

  public final void setName(String name):设置线程的名称

  针对不是Thread类的子类中如何获取线程对象名称呢?

  public static Thread currentThread():返回当前正在执行的线程对象

如果想使用setName(), getName()。需要写构造函数:

public MyThread() {

}

public MyThread(String name){

super(name);

}

 

 *  public final int getPriority():返回线程对象的优先级

 *  public final void setPriority(int newPriority):更改线程的优先级。

public static void main(String[] args) {

ThreadPriority tp1 = new ThreadPriority();

ThreadPriority tp2 = new ThreadPriority();

ThreadPriority tp3 = new ThreadPriority();

 

tp1.setName("东方不败");

tp2.setName("岳不群");

tp3.setName("林平之");

 

tp1.setPriority(10);

tp2.setPriority(1);

 

tp1.start();

tp2.start();

tp3.start();

}

 

 

方法二:实现Runnable接口

如果一个类已经有一个父类了,还想实现多线程怎么办。 

适合多个程序相同的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离

 

 *  A:自定义类MyRunnable实现Runnable接口

 *  B:重写run()方法

 *  C:创建MyRunnable类的对象

 *  D:创建Thread类的对象,并把C步骤的对象作为构造参数传递

 

public static void main(String[] args) {

MyRunnable my = new MyRunnable();

 

Thread t1 = new Thread(my, "林青霞");

Thread t2 = new Thread(my, "刘意");

 

t1.start();

t2.start();

}



 

3线程的控制和生命周期

 

 

4多线程安全问题的原因

也是我们以后判断一个程序是否有线程安全问题的依据

A:是否有多线程环境

B:是否有共享数据

C:是否有多条语句操作共享数据

 

同步解决线程安全问题

A:同步代码块

synchronized(对象) {

需要被同步的代码;

}

这里的锁对象可以是任意对象。

售票案例:

public static void main(String[] args) {

SellTicket st = new SellTicket();

 

Thread t1 = new Thread(st, "窗口1");

Thread t2 = new Thread(st, "窗口2");

Thread t3 = new Thread(st, "窗口3");

 

t1.start();

t2.start();

t3.start();

}

 

public class SellTicket implements Runnable{

private int tickets = 100;

private Object obj = new Object();

 

public void run(){

while(true){

synchronized(obj){

if(tickets > 0){

System.out.println(Thread.getCurrentThread().getName() + "  " + tickets--);

}

}

}

}

}


B: 同步方法

把同步加在方法上。(这里的锁对象是this

C:静态同步方法

把同步加在静态方法上。(这里的锁对象是当前类的字节码文件对象(反射讲了字节码文件对象)

 

public class SellTicket implements Runnable {

private static int tickets = 100;

 

private Object obj = new Object();

private Demo d = new Demo();

 

private int x = 0;

@Override

public void run() {

while (true) {

if(x%2==0){

synchronized (SellTicket.class) {

if (tickets > 0) {

System.out.println(Thread.currentThread().getName()

+ "正在出售第" + (tickets--) + "张票 ");

}

}

}else {

// synchronized (d) {

// if (tickets > 0) {

// System.out.println(Thread.currentThread().getName()

// + "正在出售第" + (tickets--) + "张票 ");

// }

// }

sellTicket();

}

x++;

}

}

 

// private void sellTicket() {

// synchronized (d) {

// if (tickets > 0) {

// System.out.println(Thread.currentThread().getName()

// + "正在出售第" + (tickets--) + "张票 ");

// }

// }

// }

//如果一个方法一进去就看到了代码被同步了,那么可以把这个同步加在方法上

//  private synchronized void sellTicket() {

// if (tickets > 0) {

// System.out.println(Thread.currentThread().getName()

// + "正在出售第" + (tickets--) + "张票 ");

// }

// }

private static synchronized void sellTicket() {

if (tickets > 0) {

System.out.println(Thread.currentThread().getName()

+ "正在出售第" + (tickets--) + "张票 ");

}

}

}

 

class Demo {

 

}



 

这个代码描述了三种同步方法。并且可以看出如何从一种方法转换成另一种。所以很好。即使很久没看,再看这个代码也可以想起来之前的思路。

 

只要是同一个锁的代码,不管里面内容是否相同,都会被锁住(当然这是极端的情况。事实上应该是为了需求而上锁的)

 

6以前讲过的线程安全的类

A:StringBuffer(因为它几乎所有方法都是方法加锁的。线程安全的类效率比较低。因为每次要对对象是否被锁上进行判断)

B:Vector

C:Hashtable

D:如何把一个线程不安全的集合类变成一个线程安全的集合类

  用Collections工具类的方法即可。

// public static <T> List<T> synchronizedList(List<T> list)

List<String> list1 = new ArrayList<String>();// 线程不安全

List<String> list2 = Collections

.synchronizedList(new ArrayList<String>()); // 线程安全


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值