多线程

nodejs多线程,真正的非阻塞

妖精的绣舞 提交于 2020-03-05 05:55:09
node从他推出至今,充满赞美和饱受诟病的都是其单线程模型,所有的任务都在一个线程中完成(I/O等例外),优势的地方自然是免去了频繁切换线程的开销,以及减少资源互抢的问题等等,但是当nodejs面对cpu密集型模型的时候就力不从心了。尽管node拥有异步机制,可以把一些耗时算法丢入eventloop等待下个事件循环再做,但是因为其任然是单线程模型,所以终究会造成阻塞。 先解释一下两个名词,Fibers 和 Threads。 Fibers 又称纤程,可以理解为协同程序,类似py和lua都有这样的模型。使用Fibers可以避免对资源的互抢,减少cpu和内存的消耗,但是Fibers并不能够真正的并行执行,同一时刻只有一个Fibers在执行,如果在其中一个Fibers中执行过多的cpu操作或者写了个死循环,则整个主程序将卡死住。node中的异步事件循环模型就有点象这个。 Threads 又称线程,他可以在同一时刻并行的执行,他们共享主进程的内存,在其中某一时刻某一个threads锁死了,是不会影响主线程以及其他线程的执行。但是为了实现这个模型,我们不得不消耗更多的内存和cpu为线程切换的开销,同时也存在可能多个线程对同一内存单元进行读写而造成程序崩溃的问题。 很多让node支持多线程的方法是使用c/c++的addon来实现,在需要进行cpu密集型计算的地方,把js代码改写成c/c++代码

Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程

那年仲夏 提交于 2020-03-05 00:36:02
队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构。 get与put方法 ''' 创建一个“队列”对象 import queue q = queue.Queue(maxsize = 10) queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。 将一个值放入队列中: q.put() 调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为True。如果队列当前为空且block为True,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为False,put方法将引发Full异常。 import queue q=queue.Queue(3) q.put(11) q.put(22) q.put(33) q.put(44,False) #queue.Full ==q.put_nowait() 将一个值从队列中取出 q.get() 调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False

Java多线程死锁例子

旧城冷巷雨未停 提交于 2020-03-04 22:09:30
目录 一、产生死锁的原因 二、如何避免死锁 一、产生死锁的原因 发生死锁的情况: 多个线程需要同时占用多个共享资源而发生需要互相死循环等待的情况,就是,两个线程互相等待着对象释放锁,一直这样僵持下去,所以导致了死锁的产生。 产生死锁代码: package com . javaagent . thread ; public class DieThread implements Runnable { public static Object obj1 = new Object ( ) ; public static Object obj2 = new Object ( ) ; private boolean flag ; public DieThread ( boolean bl ) { flag = bl ; } @Override public void run ( ) { if ( flag ) { while ( true ) { synchronized ( obj1 ) { try { Thread . sleep ( 1000 ) ; } catch ( InterruptedException e ) { e . printStackTrace ( ) ; } System . out . println ( "线程" + Thread . currentThread

并发编程系列——什么是重排序?

邮差的信 提交于 2020-03-04 21:38:01
今天就来学习下重排序相关的知识。 在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 在单线程环境下不能改变程序运行的结果; 存在数据依赖关系的不允许重排序 as-if-serial语义 as-if-serial语义的意思是, 所有的操作均可以为了优化而被重排序,但是你必须要保证重排序后执行的结果不能被改变 ,编译器、runtime、处理器都必须遵守as-if-serial语义。注意as-if-serial只保证单线程环境,多线程环境下无效。 下面我们用一个简单的示例来说明: int a = 1 ; //A int b = 2 ; //B int c = a + b; //C A、B、C三个操作存在如下关系:A、B不存在数据依赖关系,A和C、B和C存在数据依赖关系,因此在进行重排序的时候,A、B可以随意排序,但是必须位于C的前面,执行顺序可以是A –> B –> C或者B –> A –> C。但是无论是何种执行顺序最终的结果C总是等于3。 as-if-serail语义把单线程程序保护起来了,它可以保证在重排序的前提下程序的最终结果始终都是一致的。 其实对于上段代码,他们存在这样的happen-before关系: A happens-before B B happens-before C A

最简实例说明wait、notify、notifyAll的使用方法

岁酱吖の 提交于 2020-03-04 17:12:42
wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。 这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。 其中wait方法有三个over load方法: wait() wait(long) wait(long,int) wait方法通过参数可以指定等待的时长。如果没有指定参数,默认一直等待直到被通知。 以下是一个演示代码,以最简洁的方式说明复杂的问题: 简要说明下: NotifyThread是用来模拟3秒钟后通知其他等待状态的线程的线程类; WaitThread是用来模拟等待的线程类; 等待的中间对象是flag,一个String对象; main方法中同时启动一个Notify线程和三个wait线程; public class NotifyTest { private String flag = "true"; class NotifyThread extends Thread{ public NotifyThread

Java多线程学习:wait与notify方法的使用

老子叫甜甜 提交于 2020-03-04 17:12:14
在java多线程编程中,最被经常用到的便是wait与notfiy方法,这两个方法可以用来更加精确地控制被同步的代码,从而使得被同步的代码最小化,提高并发效率。 当某个类的某个方法被标记为synchronized时,这个方法在同一时间只能被一个线程访问。此时这个方法中的所有代码都是被同步的,只有当一个线程执行完所有的代码之后,下一个线程才能开始执行。当被同步的方法代码量比较小,而且每一步执行都非常快的时候仅仅使用synchronized关键字就够了。但是,如果被同步的方法里面有一些代码是可以被共享的,而且这些能够被共享的代码里面存在比较耗时的操作时,仅仅使用synchronized关键字就无法达到最高的效率,这个时候可以使用wait与notify方法来对并发访问做更进一步的控制。首先看两段代码: public class TestThread { private boolean isIdle = true; public synchronized void work(){ /* * Some work which can be shared */ try { /* * to check if we can have this object's monitor */ if(!isIdle){ System.out.println(Thread.currentThread()

记webmagic一个多线程问题排查和修复的过程

主宰稳场 提交于 2020-03-04 15:23:11
在webmagic的多线程抓取中有一个比较麻烦的问题:当Scheduler拿不到url的时候,不能立即退出,需要等到没抓完的线程都运行完毕,没有新url产生时,才能退出。之前使用Thread.sleep来实现,当拿不到url时,sleep一段时间再取,确定没有线程执行之后,再退出。 但是这种方式始终不够优雅。Java里面有wait/notify机制可以解决这种同步的问题。于是webmagic 0.4.0用wait/notify机制代替了之前的Thread.sleep机制。代码如下: while (!Thread.currentThread().isInterrupted() && stat.get() == STAT_RUNNING) { Request request = scheduler.poll(this); if (request == null) { if (threadAlive.get() == 0 && exitWhenComplete) { break; } // wait until new url added waitNewUrl(); } else { final Request requestFinal = request; threadAlive.incrementAndGet(); executorService.execute(new

多线程 定时器 Timer TimerTask

陌路散爱 提交于 2020-03-04 10:06:00
定时器是一种特殊的多线程,使用Timer来安排一次或者重复执行某个任务 1 package org.zln.thread; 2 3 import java.util.Date; 4 import java.util.Timer; 5 import java.util.TimerTask; 6 7 /** 8 * Created by coolkid on 2015/6/21 0021. 9 */ 10 public class TestTimerTask extends TimerTask { 11 @Override 12 public void run() { 13 System.out.println(new Date()); 14 } 15 16 public static void main(String[] args) { 17 Timer timer = new Timer(); 18 TestTimerTask testTimerTask = new TestTimerTask(); 19 timer.schedule(testTimerTask,1000,1000); 20 21 } 22 } E:\GitHub\tools\JavaEEDevelop\Lesson1_JavaSe_Demo1\src\org\zln\thread\TestTimerTask

多线程的安全隐患

吃可爱长大的小学妹 提交于 2020-03-04 08:28:13
资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象、同一个变量、同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 安全隐患分析: 安全隐患的解决——互斥锁: 互斥锁使用格式 @synchronized(锁对象) { // 需要锁定的代码 } 注意:锁定1份代码只用1把锁,用多把锁是无效的 互斥锁的优缺点: 优点:能有效防止因多线程抢夺资源造成的数据安全问题 缺点:需要消耗大量的CPU资源 互斥锁的使用前提: 多条线程抢夺同一块资源 相关专业术语: 线程同步 线程同步的意思是:多条线程在同一条线上执行(按顺序地执行任务) 互斥锁,就是使用了线程同步技术 原子和非原子属性: OC在定义属性时有 nonatomic 和 atomic 两种选择 atomic :原子属性,为 setter 方法加锁(默认就是 atomic ) nonatomic :非原子属性,不会为 setter 方法加锁 nonatomic 和 atomic 对比 atomic :线程安全,需要消耗大量的资源 nonatomic :非线程安全,适合内存小的移动设备 iOS开发的建议 所有属性都声明为 nonatomic 尽量避免多线程抢夺同一块资源 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力 来源: https:/

java 多线程(二)

江枫思渺然 提交于 2020-03-04 05:51:47
一、 线程 1.1多线程原理 我的java多线程(一)的那一篇博客中已经写过多线程的代码,但是很多人对原理不是很清楚,那么我们通过代码再来体现一下多线程程序。 代码如下: 自定义线程类: public class MyThread extends Thread { /* *利用继承中的特点 *将线程名称传递 进行设置 */ public MyThread ( String name ) { super ( name ) ; } /* *重写run方法 *定义线程要执行的代码 */ public void run ( ) { for ( int i = 0 ; i < 20 ; i ++ ) { //getName()方法来自父类 System . out . println ( getName ( ) + i ) ; } } } 测试类: ```java public class Demo { public static void main(String[] args) { System.out.println(“这里是main线程”); MyThread mt = new MyThread(“小强”); mt.start();//开启了一个新的线程 for (int i = 0; i < 20; i++) { System.out.println(“旺财:”+i); } } }