Java-多线程

线程

多线程原理:
程序启动时,JVM启动一个进程;
调用main()入栈时,主线程main被创建;
随着main()中语句执行,在线程对象创建后,调用其start方法时,启动一个新的线程;
此时程序就在多线程下运行;
当执行线程的任务结束,线程自动在栈内存中释放;
当所有执行线程都结束,进程就结束了。

创建多线程程序的三种方式:(还可以实现Callable接口/使用Lambda表达式创建)
方法1.继承Thread类(代码方便,但不推荐)
创建Thread接口的子类MyThread,重写run方法->
创建MyThread的对象->
调用MyThread类对象的start方法

方法2.实现Runnable接口(推荐使用)
创建Runnable接口的实现类,重写run方法->
创建Runnable实现类的对象->
创建Thread类对象,在其构造方法中传递实现类对象->
调用Thread类对象的start方法

方法2创建多线程的好处:
1.避免了单继承的局限性
一个类只能继承一个类,而实现Runnable接口后还能继承其他类,实现其他接口
2.增强了程序的扩展性,降低了程序的耦合性(解耦)
方法2把设置线程任务和开启新线程进行了分离(解耦)
实现类中重写run方法:用来设置线程任务
创建Thread类对象:用来开启新线程

方法3.匿名内部类(简化代码)例:
//方法1+3:
        new Thread() {
            @Override
            public void run() {...
            }
        }.start();
//方法2+3:
        new Thread(new Runnable() {
            @Override
            public void run() {...
            }
        }).start();

获取线程名称:
1.使用Thread类中方法getName();
String getName();                   //返回线程名称
2.先获取当前正在执行的线程,使用getName()获取线程名称
static Thread currentThread();      //返回当前正在执行的线程对象的引用

Thread.currentThread().getName()      //在main方法中写此语句:获取主线程名称

设置线程名称:
1.使用Thread类中的方法setName
void setName(String name)   
2.创建带参数构造方法(参数传递线程名称);调用父类的带参构造方法,让父类给子线程起一个名字
Thread(String name)

public static void sleep(long millis);使当前正在执行的线程以指定毫秒数暂停
Thread.sleep(1000);  //可以使用try catch和声明异常throws两种方式
解决线程安全问题的方法
1.同步代码块
synchronized(锁对象){
    可能出现线程安全问题的代码(访问了共享数据的代码)
}
锁对象可以是任意对象(this也可以,但最好不要用)

2.使用同步方法
把访问了共享数据的代码抽取出来,放在一个方法中
在方法上添加synchronized修饰符

(同步方法的锁对象就是实现类对象,即this)
注:静态同步方法
静态方法优先于对象,其锁对象不能是this
锁对象:本类的class属性-->class文件对象(反射)

3.Lock锁
在成员位置创建ReentrantLock对象
在可能会出现安全问题的代码前调用Lock接口中的lock方法获取锁
在可能会出现安全问题的代码后调用unlock方法释放锁
线程6种状态:
NEW(新建状态、初始化状态)
RUNNABLE(可运行状态、就绪状态)
BLOCKED(阻塞状态、被中断运行)
WAITING(等待状态)
TIMED_WAITING(定时等待状态)
TERMINATED(死亡状态、终止状态)

Object类中的方法:
void wait()
    在其他线程调用此对象的notify()或notifyAll()方法前,使线程进入等待状态
void notify()
    唤醒在此对象监视器上等待的单个线程 (优先唤醒等待时间最长的)
    会继续执行wait方法后的代码
notifyAll:唤醒此对象监视器上等待的所有线程

使用注意:
wait和notify方法必须放在同步代码块或同步方法中,且两者由同一个锁对象调用。
wait和notify方法属于Object类,任何对象都可使用。
sleep()方法和wait()方法的区别:

1.所属类
sleep()是Thread类的(静态)方法,wait()是自Object类的方法

2.(关键☆)释放锁
sleep()方法没有释放锁,wait()方法释放了锁:
使得其他等待此 同步资源(锁) 的线程可以使用同步控制块或方法

3.使用限制
wait,notify和notifyAll必须在synchronized块中使用,而sleep可以在任何地方使用

4.使用场景
sleep一般用于线程休眠、循环控制,wait多用于多线程之间通信
线程池:
容纳多个线程的容器,其中线程可以反复使用,省去了频繁创建线程对象的操作:
降低资源消耗,提高响应速度,提高线程的可管理性

容器-->集合    (  LinkedList<Thread>  )
当程序第一次启动时,创建多个线程,保存在一个集合中;
当想要使用线程时,就从集合中取出线程使用;
使用完毕线程后,需要把线程归还给线程池

在JDK1.5之后,JDK内置了线程池,可以直接使用


线程池的使用步骤:
1.使用线程池工厂类Executors中的静态方法newFixedThreadPool生产一个指定数量的线程池
        ExecutorService es = Executors.newFixedThreadPool(2);

2.创建一个类,实现Runnable接口,设置线程任务
    public class RunnableImpl implements Runnable {
        @Override
        public void run() {...}
    }

3.调用ExecutorService中的submit()方法,传递线程任务(实现类),开启线程
        es.submit(new RunnableImpl());

4.调用ExecutorService中的shotdown()方法,销毁线程池(不建议执行)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值