java基础_线程
什么是线程
>>线程是每一个进程执行的顺序,该顺序是一个执行路径,或者叫做一个控制单元。
简单来说线程就是一个控制单元或者叫做一个执行路径。
>>是程序执行流的最小单位
_____________________________________________________________________________________________________________________________________________________________
什么是进程
>>进程是一个正在执行的程序。
>>进程是资源分配的基本单位。
__________________________________________________________________________________________________________________________________________________________________
进程和线程的关系
每个进程至少有一个线程(线程是进程的一个实体,是被系统独立调度和分派的基本单位)
______________________________________________________________________________________________________________________________________________________________________
什么是多线程
在当个程序中运行多个线程完成不同的工作。
多线程具有随机性
___________________________________________________________________________________________________________________________________________________________________
生活中的例子
比如说,政府的行政楼,里面有很多办事窗口,每一个办事窗口相当于一个线程,行政楼相当于进程
多线程就是相当于行政楼多个窗口
____________________________________________________________________________________________________________________________________________________________________
在代码中定义一个执行线程的步骤
方法(一)
>>继承Thread类
>>重新run()方法
>>调用start()方法
>>启动线程
>>调用run()方法
在主函数中调用run方法和调用start方法的区别
>>直接调用run方法,相当于对象调用方法,这样我们创建了线程,并没有实际上运行了线程,产生的效果就是线执行run,然后在执行主函数(意思就是只有主函数这个线程在执行,我们定义的线程并没有执行)
___________________________________________________________________________________________________________________________________________________________________________________________________
方法(二)
>>声明实现Runnable接口的类(implements Runnable)
>> 实现Runnable接口的run方法,
>>然后可以分配该类的实例
创建实例对象 比如说买票系统里的Tick t=new Tick()
>>在创建thread时作为一个参数来传递并启动。
因为这里的run方法指的是Runnable里的run方法,不是Thread的run方法
简单意思就是 Thread t1=new Thread(t) t1.start();
实现方式(接口)和继承方式区别:
>>避免了单继承的局限性(定义线程时候,最好采用实现的方式)
>>实现的方式实现了资源的独立共享
对于继承Thread:线程代码存放在Thread子类的run方法中
对于实现,是存放在接口的子类的run方法中
______________________________________________________________________________________________________________________________________________________________________
线程具有默认的名称
>>getName();
>>默认的格式 Thread_编号(0开始)
>>thread.currentThread==this.getName(); 静态的,获取当前线程对象
>>setName或者构造函数(Thread(String name){super(name);})
_______________________________________________________________________________________________________________________________________________________________________
多线程容易产生安全问题
>>模拟多线程的安全问题的产生
>> //try{Thread.sleep(10);}case(Exception e){}
>>产生问题的原因:
>>当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的失误
>>解决办法:
>>对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不能参与执行。
>>同步代码块可以解决这个问题
>>synchronized(对象){
需要被同步的代码块(那些语句在操作共享数据代码)
}
>>同步代码块中的对象如锁,持有锁的线程可以在同步中执行
没有持有锁的线程即使获得cpu的执行权,也进不去,因为没有获取锁,
>>同步函数也可以解决这个问题
>>public synchronized void add(){函数体}
同步的前提:
>>必须要有两个或者两个以上的线程
>>必须是多个线程使用同一个锁(即使操纵同一个共享数据)
好处:
>>解决了多线程的安全的问题
弊端:
>>较为消耗了资源,程序变得比较慢(因为每次都需要判断锁)
______________________________________________________________________________________________________________________________________________________
同步函数是怎么实现锁的功能,有是用什么锁控制多线程的呢?
>>因为函数被对象调用,那么谁调用这个函数,那么这个锁就是该对象的锁,所以同步函数的锁就是this
>>可以通过一个写同步代码块,一个用同步函数,来实现判断同步函数是不是this
>>如果不出现错误的票,即使使用同一个锁
>>static synchronized void show()使用的锁是class字节码对象(Tick.class)
class Ticket implements Runnable{
private /*static*/ int tick=100;
boolean flag=true;
//为同步代码块提供的对象
//object obj=new object();
public void run(){
while(tick>0){
//模拟多线程出现安全隐患
//try{Thread.sleep(10);}case(Exception e){}
//可以这个解决多线程出现安全隐患
if (flag){
//synchronized(obj)-->synchronized(this)
synchronized(this){
try{Thread.sleep(10);}case(Exception e){}
if(tick>0){
System.out.println(Thread.currentThread().getName()+" "+"Runnable sale:"+tick--);
}
}
}else{show()}
}
}
}
public synchronized void show{
if(tick>0){
System.out.println(Thread.currentThread().getName()+" "+"show sale:"+tick--);
}
}
public class TicketDemo{
public static void main(String args[]){
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag=flase;
t2.start();
}
}
________________________________________________________________________________________________________________________________________________________
>>static synchronized void show()使用的锁是class字节码对象(Tick.class)
class Ticket implements Runnable{
private static int tick=100;
boolean flag=true;
//为同步代码块提供的对象
//object obj=new object();
public void run(){
while(tick>0){
//模拟多线程出现安全隐患
//try{Thread.sleep(10);}case(Exception e){}
//可以这个解决多线程出现安全隐患
if (flag){
//synchronized(obj)-->synchronized(Tick.class)
synchronized(Tick.class){
try{Thread.sleep(10);}case(Exception e){}
if(tick>0){
System.out.println(Thread.currentThread().getName()+" "+"Runnable sale:"+tick--);
}
}
}else{show()}
}
}
}
public static synchronized void show{
if(tick>0){
System.out.println(Thread.currentThread().getName()+" "+"show sale:"+tick--);
}
}
public class TicketDemo{
public static void main(String args[]){
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag=flase;
t2.start();
}
}
____________________________________________________________________________________________________________________________________________________
//单例设计
>>饿汉式
class single{
private static void final single sin=new single();
privaate Single(){}
public static single getInstance(){
return s;
}
}
//懒汉式
class single{
private static single sin=null;
private single(){}
public static single getInstance(){
if(s==null){s=new single();}
return s;
}
}
//
__________________________________________________________________________________________________________________________________________________________________
//死锁
>>同步中嵌套同步式出现死锁的原因
class Test implements Runnable{
private boolean flag;
Test(boolean flag){this.flag=flag}
public void run(){
if(falge){
synchronized(mylock.locaka){
System.out.prinlnt("if locaka");
synchronized(mylock.locakb){
System.out.prinlnt("if locakb");
}
}else{
synchronized(mylock.locakb){
System.out.prinlnt("else locakb");
synchronized(mylock.locaka){
System.out.prinlnt("else locaka");
}
}
}
}
class mylock{
static Object locka=new Object();
static Object locka=new Object();
}
public class DeadLockTest{
public static void main(){
Thread t1=new Thread(new Test(true));
Thread t2=new Thread(new Test(false));
t1.start();
t2.start();
}
}
____________________________________________________________________________________________________________________________________________
线程间的通信
>>等待唤醒机制
>>wait; notify(); notifyAll();都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步中这才有具有锁
为什么这些操作线程的方法要定义Object类中呢?
>>因为这些方法在操作同步线程时,都必须要标识他们所操作线程只有锁
只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒
不可以对不同锁中的线程进行唤醒,也就是说等待和唤醒必须时同一个锁,而锁可以时任意对象,
所以可以被任意对象调用的方法定义Object类中
jdk升级了多线程解决锁和唤醒机制
>>lock代替了synchroinzed
>>condition对像代替了notify和wait以及notifyAll的Object对象
________________________________________________________________________________________________________________
停止线程
>>如何停止线程能,只有一种方法停止,run结束
开启多线程运行,通常都是循环结构,只要控制循环,就可以让线程run()结束
//run方法结束停止线程
//通过控制循环的标签来控制run的结束
//但是有一种情况
//当线程处于冻结的状态,线程就不会结束,可以用interrupt恢复运行状态,这样在catch里将循环的状态变成flag=false,就可以结束run()[线程]
_____________________________________________________________________________________________________________________________________
守护线程
>>后台线程(即是守护线程)当所有的前台线程(主线程)结束后,后台线程自动结束
>>使用守护线程,必须要在开启线程前,使用t1.setDaemon(true);
_________________________________________________________________________________
join加入线程
>>意思是当使用线程.jion时候,cpu的执行权就会交给申请的线程运行
————————————————————————————————————————
线程的优先级
>>线程.setPriority(Thread.MAX_PRIORITY);1-10级
>>Thread.yield :临时暂停,可以达到线程的交替使用
——————————————————————————————————————
线程的应用场景
>>当某些代码需要同是被执行时,用线程进行封装。
匿名内部类的写法
new Thread(){
public void run(){
}
}.start();