一、多线程概念
1、进程:正在进行中的程序。是一个应用程序在内存中一片内存空间。
2、线程:其实就是进程中一个程序执行控制单元,一条执行路径。进程负责的是应用程序的空间的标示。线程负责
的是应用程序的执行顺序。
3、一个进程中至少要有一个线程。 当一个进程中线程有多个时,就是多线程。
4、多线程解决的问题:可以让多部分代码同时执行。
5、什么是同时执行呢?其实都是cpu在瞬间做着快速切换完成的。cpu的切换随机的,按照时间片的方式来完成。
6、线程要运行的代码都统一存放在了run方法中。
7、线程要运行必须要通过类中指定的方法开启。start方法。
8、java运行就是多线程的:在执行main函数中内容的同时,垃圾回收器也在回收堆内存的垃圾。所以执行main方法
的线程,和执行垃圾回收器的线程同时在执行。这就是多线程。
二、创建线程有两种方式
1)第一种方式:继承Thread ,由子类复写run方法。
步骤:
a,定义类继承Thread类;
b,目的是复写run方法,将要让线程运行的代码都存储到run方法中;
c,通过创建Thread类的子类对象,创建线程对象;
d,调用线程的start方法,开启线程,并执行run方法。
//通过继承Thread类来实现四个窗口卖票,一共有100张票
class Ticket extends Thread
{
private static int num = 100;
public void run()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"....sale...."+num--);
}
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
Ticket t3 = new Ticket();
Ticket t4 = new Ticket();
t1.start();
t2.start();
t3.start();
t4.start();
}
}
1)创建线程的第二种方式:实现一个接口Runnable。
步骤:
a,定义类实现Runnable接口。
b,覆盖接口中的run方法(用于封装线程要运行的代码)。
c,通过Thread类创建线程对象;
d,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。
e,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
//通过实现Runnable接口来实现四个窗口卖票,一共有100张票
class Ticket implements Runnable
{
private int num = 100;
public void run()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+".....sale....."+num--);
}
}
}
}
class TicketDemo2
{
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();
}
}//实现Runnable接口可以避免单继承的局限性。
三、线程安全问题
1、一个线程在执行多条语句时,并运算同一个数据时,在执行过程中,其他线程参与进来,并操作了这个数据。导
致到了错误数据的产生。
2、原因:多条语句在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。
3、解决方式:就是同步代码块。
四、同步
1、格式:
synchronized(对象)//对象可以是任意的对象。
{
需要被同步的语句。
}
2、同步的原理:其实就是将需要同步的代码进行封装,并在该代码上加了一个锁(锁就是对象)。
3、同步的好处:解决多线程的安全问题。
4、同步的弊端:会降低性能。
5、同步的前提:
1)必须要保证在同步中有多个线程。因为同步中只有一个线程该同步是没有意义。
2)必须要保证多个线程在同步中使用的是同一个锁。
6、同步函数
1)同步函数其实就是将同步关键字定义在函数上,让函数具备了同步性。
2)在函数上加上synchronized修饰符即可。
3)同步函数用的锁:函数都有自己所属的对象this,所以同步函数所使用的锁就是this锁。
7、同步函数和同步代码块的区别:
a同步函数比同步代码块写法简单。
b同步代码块使用的锁可以是任意对象。(建议开发时,使用同步代码块。尤其是需要不同锁时。)
c同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象(这个对象的表示方式 类名.class 它就表示字节码文件对象) 。