1.多线程
进程:正在运行的应用程序在内存中分配的空间
线程:是进程中负责程序执行的执行单元,也称执行路径一个进程中至少有一个线程在负责该进程的运行
多线程技术:解决多部分代码同时执行的需求,合理使用cpu资源,提高用户体验。(微观上串行,并未实际上提高效率)
多线程的运行是根据cpu的切换完成的,具有不确定性。
jvm中的多线程(至少2个):一个负责代码的运行,这个从main方法执行的线程称为主线程。
一个负责垃圾回收(不定时)
每一个线程都有运行代码的内容,称之为线程的任务。线程的任务都封装在特定的区域中。
主线程运行的任务都定义在main方法中
垃圾回收线程(finalize)在收垃圾时会运行finalize()方法。
class Demo{
public void finalize(){//垃圾回收方法,即释放资源。不保证该函数一定会被调用
System.out.println("demo recycle");
}
}
class FinalizeDemo{
public static void main(String[] args)
{
new Demo();
new Demo();
new Demo();
new Demo();
System.gc();//启动垃圾回收器,不一定调用finalize(),由cpu切换造成的不确定性
System.out.println("Hello World!");
}
}
2.创建多线程的两种方法
1)继承Thread类
继承Thread
覆盖run()
创建子类对象就是创建线程对象
调用Thread类中的start(),同时会调用run()
注意:start()开启线程后,都会调用run(),所以run()中存储的都是线程要运行的代码。
调用run()和调用start()的区别:
调用start()会开启线程,并用开启的线程去执行run()方法中的内容
调用run()不会开启线程,执行run()方法中内容的是main线程
class Demo extends Thread
{
private String name;
Demo(String name){
this.name = name;
}
public void show(){
for(int i = 1;i <= 10;i++)
System.out.println(Thread.currentThread().getName()+"...."+name+"........"+i);
}
//Thread.currentThread()获取当前运行线程的引用
//getName()获取线程的名字
public void run(){
show();
}//覆盖run()
}
class ThreadDemo
{
public static void main(String[] args)
{
Demo d1 = new Demo("Jack");
Demo d2 = new Demo("Tom");
d1.start();
d2.start();
for(int i = 1;i <= 10;i++)
System.out.println(Thread.currentThread().getName()+"----"+"MainThread"+"......"+i);
}
}
2)实现Runnable接口
1)定义一个类实现Runnable
2)覆盖Runnable接口中的run方法,将线程要运行的任务代码存储到该方法中
3)通过Thread类创建线程对象,并将实现了Runnable接口的对象作为Thread类的构造函数的参数进行传递
4)调用Thread类的start方法,开启线程
注意:此方法将线程对象和线程任务分开了
实现Runnable接口的好处:
1)避免了继承Thread类的单继承的局限性
2)Runnable接口的出现更符合面向对象,将线程单独进行对象的封装
3)Runnable接口的出现,降低了线程对象和线程任务的耦合性
所以开发多用实现Runnable接口。
多线程的安全问题:
产生原因:
1)线程任务处理到共享数据
2)线程任务中有多条对共享数据的操作
解决思想:
互斥地访问临界资源
解决办法:
同步代码块(未操作共享数据的代码无需同步)
synchronized(object){
需要被同步的代码
}
同步的前提:
多线程在同步中必须使用同一个锁(object)
class SaleTicket implements Runnable
{
private int tickets = 100;
Object obj = new Object();//synchronized(obj),相当于“锁”
public void run(){
while(true){
synchronized(obj){//同步代码块
if(tickets > 0){
try{
Thread.sleep(10);//线程停止执行10ms
}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"...."+tickets--);
}
}
}
}
}
class TicketSystem
{
public static void main(String[] args)
{
SaleTicket t = new SaleTicket();
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();
}
}