首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
80 阅读
2
nvim番外之将配置的插件管理器更新为lazy
58 阅读
3
2018总结与2019规划
54 阅读
4
PDF标准详解(五)——图形状态
33 阅读
5
为 MariaDB 配置远程访问权限
30 阅读
心灵鸡汤
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
archlinux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
菜谱
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
登录
Search
标签搜索
c++
c
学习笔记
windows
文本操作术
编辑器
NeoVim
Vim
win32
VimScript
Java
emacs
linux
文本编辑器
elisp
反汇编
OLEDB
数据库编程
数据结构
内核编程
Masimaro
累计撰写
308
篇文章
累计收到
27
条评论
首页
栏目
心灵鸡汤
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
archlinux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
菜谱
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
页面
归档
友情链接
关于
搜索到
1
篇与
的结果
2019-07-07
Java 多线程
Java内部提供了针对多线程的支持,线程是CPU执行的最小单位,在多核CPU中使用多线程,能够做到多个任务并行执行,提高效率。使用多线程的方法创建Thread类的子类,并重写run方法,在需要启动线程的时候调用类的start() 方法,每一个子类对象只能调用一次start()方法,如果需要启动多个线程执行同一个任务就需要创建多个线程对象实现Runnable 接口并重写run 方法,传入这个接口的实现类构造一个Thread类,然后调用Thread类的start方法实现Callable 接口并重写call方法,然后使用Future 来包装 Callable 对象,使用 Future 对象构造一个Thread对象,并调用Thread 类的start方法启动线程平时在使用上第一个方式用的很少,一般根据情况使用第2中或者第3中,与第一种方式相比,它们具有的优势如下:降低了程序的耦合性,它将设置线程任务和开启线程进行了分离避免了单继承的局限性,一旦继承了Thread 类,那么他就不能继承其他类。使用重写接口的方式可以再继承一个别的类第3中方式相比第二种方式来说,它提供了一个获取线程返回值的方式。我们在call函数中返回值,通过 FutureTask 对象的get方法来获取返回值public class ThreadTask extends Thread{ @Override public void run(){ System.out.println("当前线程:" + getName() + "正在运行"); } } public class ThreadDemo{ public static void main(String[] args){ new ThreadTask().start(); new ThreadTask().start(); } }public class ThreadDemo{ public static void main(String[] args){ //使用匿名内部类的方式 Runnable thread1 = new Runnable(){ @Override public void run(){ System.out.println("当前线程:" + Thread.currentThread().getName() + "正在运行"); } } new Thread(thread1).start(); new Thread(thread1).start(); } }public class ThreadDemo implements Callable<Integer>{ public static void main(String[] args){ FutureTask<Integer> ft = new new FutureTask<>(new ThreadDemo()); new Thread(ft).start(); System.out.println("线程返回值:" + ft.get()); } @Override public Integer call() throws Exception { System.out.println("当前线程:" + Thread.currentThread().getName() + "正在运行"); return 1; } }thread 状态在操作系统原理中讲到,线程有这么几种状态:新建、运行、阻塞、结束。而Java中将线程状态进行了进一步的细分,根据阻塞原因将阻塞状态又分为:等待(调用等待函数主动让出CPU执行权), 阻塞(线程的时间片到达,操作系统进行线程切换)它们之间的状态如下:等待唤醒入上图所示,可以使用wait/sleep方法让线程处于等待状态。在另一个线程中使用wait线程对象的notify方法可以唤醒wait线程。wait/notify 方法定义于 Object 方法,也就是说所以的对象都可以有wait/notify 方法。void wait() ;调用该函数,使线程无限等待,直到有另外的线程将其唤醒 void wait(long timeout);调用该函数,使线程进行等待,直到另外有线程将其唤醒或者等待时间已过 void notify(); 唤醒正在等待对象监视器的单个线程 void notifyAll(); 唤醒正在等待对象监视器的所有线程。上面说过这些方法都是在 Object 类中实现的,也就是说所有的对象都可以调用。上面的等待监视器就是随意一个调用了wait 的对象。这个对象会阻塞它所在的线程。线程同步我们知道在访问多个线程共享的资源时可能会发生数据的安全性问题。因此这个时候需要做线程的同步Java中同步的方法有: 同步代码块、同步方法和Lock锁的机制同步代码块同步代码块是使用synchronized来修饰需要进行同步的代码块同步代码块需要提供一个锁对象,当一个线程执行到这个代码块时,该线程获得锁对象。当另外的线程也执行到同一个锁对象的同步代码块时,由于无法获取到锁对象因此会陷入等待。直到获得锁对象的线程执行完同步代码块,并释放锁。这里获取、释放锁由Java虚拟机自己完成。例如public static void synchronizedCode(){ Runnable thread = new Runnable(){ private int ticket = 100; @Override public void run(){ synchronized (this){ while(ticket > 0){ //这里休眠10s,用来表示提交订单后的付款等操作 try{ Thread.sleep(10); }catch(Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket); ticket--; } System.out.println(Thread.currentThread().getName() + "票已售罄"); } } }; new Thread(thread).start(); new Thread(thread).start(); new Thread(thread).start(); }同步方法同步方法是使用 synchronized 关键字修饰的方法。它与同步代码块的原理相同,保证了多个线程只有一个处于同步代码块中。同步方法中也有一个锁对象,这个锁对象是this这个对象,静态方法的锁对象是本类的class文件对象。public static void synchronizedMethod(){ Runnable thread = new Runnable(){ private int ticket = 100; @Override public void run(){ payTicket(); } public synchronized void payTicket(){ while(ticket > 0){ //这里休眠10s,用来表示提交订单后的付款等操作 try{ Thread.sleep(10); }catch(Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket); ticket--; } System.out.println(Thread.currentThread().getName() + "票已售罄"); } }; new Thread(thread).start(); new Thread(thread).start(); new Thread(thread).start(); }Lock 锁机制除了上述方法,可以使用lock锁来进行同步,在执行代码前先调用 lock方法获得锁,执行完成之后使用unlock 来释放锁。例如下列的例子public static void lockMethod(){ Runnable thread = new Runnable(){ private int ticket = 100; private Lock lock = new ReentrantLock(); @Override public void run(){ try{ lock.lock(); while(ticket > 0){ //这里休眠10s,用来表示提交订单后的付款等操作 Thread.sleep(10); System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket); ticket--; } }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } System.out.println(Thread.currentThread().getName() + "票已售罄"); } }; new Thread(thread).start(); new Thread(thread).start(); new Thread(thread).start(); }
2019年07月07日
5 阅读
0 评论
0 点赞