您的位置:首页 > 职场人生

黑马程序员——多线程知识总结1

2015-08-01 14:31 561 查看
-------
android培训、java培训、期待与您交流! ----------
多线程算是Java中比较重要的一个部分了,下面把个人觉得的一些重要内容和大家分享下~~

概述

进程:正在执行中的程序

线程:进程中一个负责程序执行的控制单元(执行路径)。

P.S.

1、一个进程中可以有多个执行路径,称之为多线程。

2、一个进程中至少要有一个线程。

多线程的好处:解决了多部分代码同时运行的问题。

多线程的弊端:线程太多,会导致效率的降低。

其实,多个应用程序同时执行都是CPU在做着快速的切换完成的。这个切换是随机的。CPU的切换是需要花

费时间的,从而导致了效率的降低。————>多线程的实质(⊙o⊙)哦。

在单线程程序中,只有上一句代码执行完,下一句代码才有执行的机会。

如何定义一个线程?

创建线程方式一:继承Thread类

1.定义一个类继承Thread类。

2.覆盖Thread类中的run方法。

3.直接创建Thread的子类对象创建线程。

4.调用start方法开启线程并调用线程的任务run方法执行。

run方法中定义的就是线程要运行的任务代码。

P.S.

继承Thread类的类对象调用start方法开启了线程,并执行线程的run方法;

而直接调用run方法,仅仅是对象调用方法,没有新线程开启;

创建线程方式二:实现Runnable接口

1.定义类实现Runnable接口。

2.覆盖接口中的run方法,将线程的任务代码封装到run方法中。

3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。

4.调用线程对象的start方法开启线程。

方式二更为常用~~(Java中是单继承,使用方式二避免了Java单继承的局限性。)

其实下面才是重点——多线程的安全性

问题的原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,

另一个线程参与进来执行。导致共享数据的错乱。

解决办法:

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

在java中,用同步代码块就可以解决这个问题。

同步代码块的格式:

synchronized(对象){

需要被同步的代码;其实就是操作共享数据的语句

}

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

同步的好处:解决了线程的安全问题。

同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,无形中会降低程序的运行效率。

同步的前提:必须有多个线程并使用同一个锁。

当synchronized出现在函数声明上,函数就具备了同步性(同步函数)

利用同步代码块解决安全问题案例:

/*
需求:
银行有一个金库。
有两个储户分别存300元,每次存100,存3次。

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

*/

class Bank
{
private int sum;//金库金额
public void add(int n)
{
synchronized(this)
{
sum = sum + n;
System.out.println("sum="+sum);
}
}
}

class ChuHu implements Runnable
{
private Bank b = new Bank();
public void run()//储户向金库存钱

{
for(int x=0; x<3; x++)
{
b.add(100);
}
}
}

class  BankDemo
{
public static void main(String[] args)
{
ChuHu c = new ChuHu();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}


同步函数和同步代码块的区别:

1.同步函数的锁是固定的this。

2.同步代码块的锁是任意的对象。

静态的同步函数使用的锁是该函数所属字节码文件对象,可以用当前类名.class表示。

总结完各种同步后,提醒各位小心死锁(同步中嵌套同步,但个同步中锁不一样)

上个死锁的例子,小心避免啊

class Test implements Runnable
{
private boolean flag;//标记位,好让下面出现死锁
Test(boolean flag)
{
this.flag = flag;//两线程创建时传入不同标记
}

public void run()
{
if(flag)//标记位true的到这来
{
while(true)
{
synchronized(MyLock.locka)//持有locka
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb)//标记位false的线程持有lockb时,这里就停住进不去了
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else//标记位false的
{
while(true)
{
synchronized(MyLock.lockb)//持有lockb
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka)//当上面的持有locka这里就停这了
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
}

//封装两个锁方便使用
class MyLock
{
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();
}
}


额,先到这里,下回在更
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: