精华内容
下载资源
问答
  • c++中多线程编程是不是线程数越多越好

    千次阅读 多人点赞 2013-10-05 12:41:26
    多线程编程可以提高程序的并发执行能力,那是不是线程越多越好呢?

    多线程编程可以提高程序的并发执行能力,那是不是线程越多越好呢?

    大家可以参考下面的代码做测试:

    #define  MAX_WORKTHREAD		5
    map<int, int> m_task;//用于统计每个线程做的任务数
    std::deque<int> m_MsgQueue;//处理的消息队列
    	for (i=0; i<MAX_WORKTHREAD; i++)
    	{
    		int* nTemp = new int;
    		*nTemp = i;
    		hWTHandle[i] = CreateThread(NULL, 0, WorkThread, nTemp, 0, &g_dwWorkThread[i]); 
    		WorkThreadCout ++;
    		m_task[i] = 0;
    		Sleep(100);
    	}
    	
    DWORD WINAPI WorkThread(LPVOID lpParam)  
    {   
    	// cout << "No." << g_dwThreadID << " thread is running." << endl;  
    	while (TRUE)  
    	{  
    		int* nRemp = (int*)lpParam;
    
    		int n = -1;
    
    		EnterCriticalSection(&g_cs);
    		//cout << "No " << *nRemp << ", " << g_dwWorkThread[*nRemp] << " thread is running." << endl;
    		LeaveCriticalSection(&g_cs);
    
    		EnterCriticalSection(&g_MsgQueue);
    		if (!m_MsgQueue.empty())
    		{
    			n = m_MsgQueue.front();
    			m_MsgQueue.pop_front();
    		
    			m_task[*nRemp]++;
    		}
    		LeaveCriticalSection(&g_MsgQueue);
    
    		EnterCriticalSection(&g_cs);
    		cout << "No:" << *nRemp << ", " << n << endl;
    		LeaveCriticalSection(&g_cs);
    
    		Sleep(2000);//备注1
    
    	}  
    
    	cout << "No " << lpParam << " end" << endl;
    
    	return 0;  
    }

    当任务执行完了后,可以打印m_task里的数据:

    std::map<int, int>::iterator IterCount;
    for(IterCount=m_task.begin(); IterCount!=m_task.end();IterCount++)
    {
    	int nThreadId= (*IterCount).first;
    	int nCount = (*IterCount).second;
    					
    	EnterCriticalSection(&g_cs);
    	cout << "nThreadId:" << nThreadId << ", nCount" << nCount<<endl;
    	LeaveCriticalSection(&g_cs);
    
    	(*IterCount).second = 0;
    }


    可以修改备注1处的Sleep(2000),分别改为1000,3000,5000,10000等看看结果有什么区别?这里的时间其实是模拟执行一个任务所需要的时间,也可以用随机函数随机产生。

    另外,多线程操作全局变量的时候,一定要用线程同步(如临界区等)来操作,否则,会有问题。在使用的过程中,一定要注意资源和线程之间的关系,避免死锁发生。

    经过测试,多线程中的线程数是不是越多越好?这个问题的答案应该就有了。


    转载请注明原创链接:http://blog.csdn.net/wujunokay/article/details/12307773







    展开全文
  • 线程越多越好吗?

    2021-09-14 19:54:34
    (2)一段时间内线程越多越好,效率越来越高。(错) 2.原因 (1)假设现有8个CPU、8个线程,每个线程占用一个CPU,同一时间段内,若8个线程都运行往前跑,相比较5/6/7个线程,8个线程的效率高。 (2)但若此时有9个...

    文章目录

    1.判断题

    先来看两道判断题
    (1)一段空间内线程并发的数量越多,程序效率越高。(错)
    (2)一段时间内线程越多越好,效率越来越高。(错)

    2.原因

    (1)假设现有8个CPU、8个线程,每个线程占用一个CPU,同一时间段内,若8个线程都运行往前跑,相比较5/6/7个线程,8个线程的效率高。
    (2)但若此时有9个线程,只有8个CPU,9个线程同时运行,则此时牵扯到线程切换,而线程切换是需要消耗时间的。
    (3)所以随着线程数越多,效率越来越高,但到一个峰值,再增加线程数量时,就会出现问题。线程太多要来回的切换,最终可能线程切换所用时间比执行时间业务所用时间还大。
    (4) 随着线程数越多,由于线程执行的时序的问题,程序可能会崩溃或产生二义性。

    展开全文
  • Less is More这次越多越好 走近世界之最的多线程、多核心处理器.pdf
  • C++编程中是不是线程越多越好

    千次阅读 2014-03-09 09:20:24
    多线程编程可以提高程序的并发执行能力,那是不是线程越多越好呢? 大家可以参考下面的代码做测试: [cpp] view plaincopy #define MAX_WORKTHREAD 5  mapint, int> m_task;//...

    多线程编程可以提高程序的并发执行能力,那是不是线程越多越好呢?

    大家可以参考下面的代码做测试:

    [cpp]  view plain copy
    1. #define  MAX_WORKTHREAD     5  
    2. map<intint> m_task;//用于统计每个线程做的任务数  
    3. std::deque<int> m_MsgQueue;//处理的消息队列  
    4.     for (i=0; i<MAX_WORKTHREAD; i++)  
    5.     {  
    6.         int* nTemp = new int;  
    7.         *nTemp = i;  
    8.         hWTHandle[i] = CreateThread(NULL, 0, WorkThread, nTemp, 0, &g_dwWorkThread[i]);   
    9.         WorkThreadCout ++;  
    10.         m_task[i] = 0;  
    11.         Sleep(100);  
    12.     }  
    13.       
    14. DWORD WINAPI WorkThread(LPVOID lpParam)    
    15. {     
    16.     // cout << "No." << g_dwThreadID << " thread is running." << endl;    
    17.     while (TRUE)    
    18.     {    
    19.         int* nRemp = (int*)lpParam;  
    20.   
    21.         int n = -1;  
    22.   
    23.         EnterCriticalSection(&g_cs);  
    24.         //cout << "No " << *nRemp << ", " << g_dwWorkThread[*nRemp] << " thread is running." << endl;  
    25.         LeaveCriticalSection(&g_cs);  
    26.   
    27.         EnterCriticalSection(&g_MsgQueue);  
    28.         if (!m_MsgQueue.empty())  
    29.         {  
    30.             n = m_MsgQueue.front();  
    31.             m_MsgQueue.pop_front();  
    32.           
    33.             m_task[*nRemp]++;  
    34.         }  
    35.         LeaveCriticalSection(&g_MsgQueue);  
    36.   
    37.         EnterCriticalSection(&g_cs);  
    38.         cout << "No:" << *nRemp << ", " << n << endl;  
    39.         LeaveCriticalSection(&g_cs);  
    40.   
    41.         Sleep(2000);//备注1  
    42.   
    43.     }    
    44.   
    45.     cout << "No " << lpParam << " end" << endl;  
    46.   
    47.     return 0;    
    48. }  

    当任务执行完了后,可以打印m_task里的数据:

    [cpp]  view plain copy
    1. std::map<intint>::iterator IterCount;  
    2. for(IterCount=m_task.begin(); IterCount!=m_task.end();IterCount++)  
    3. {  
    4.     int nThreadId= (*IterCount).first;  
    5.     int nCount = (*IterCount).second;  
    6.                       
    7.     EnterCriticalSection(&g_cs);  
    8.     cout << "nThreadId:" << nThreadId << ", nCount" << nCount<<endl;  
    9.     LeaveCriticalSection(&g_cs);  
    10.   
    11.     (*IterCount).second = 0;  
    12. }  


    可以修改备注1处的Sleep(2000),分别改为1000,3000,5000,10000等看看结果有什么区别?这里的时间其实是模拟执行一个任务所需要的时间,也可以用随机函数随机产生。

    另外,多线程操作全局变量的时候,一定要用线程同步(如临界区等)来操作,否则,会有问题。在使用的过程中,一定要注意资源和线程之间的关系,避免死锁发生。

    经过测试,多线程中的线程数是不是越多越好?这个问题的答案应该就有了。






    原创链接:http://blog.csdn.net/wujunokay/article/details/12307773

    展开全文
  • Java应用中线程是不是开的越多越好,开多少合适,如何减少上下文切换开销?,如何写个shell脚本获取上下文切换的开销?
  • 多线程

    千次阅读 2019-02-01 17:46:22
    java中的多线程是一个同时执行多个线程的进程,线程是一个轻量级的子进程,是最小的处理单位。线程是进程的一条执行路径, 而进程是线程的集合。 1.优点:  ① 他不会阻塞用户,因为线程是独立的,可以同时执行...

    java中的多线程是一个同时执行多个线程的进程,线程是一个轻量级的子进程,是最小的处理单位。线程是进程的一条执行路径,

    而进程是线程的集合。

    1.优点:

             ① 他不会阻塞用户,因为线程是独立的,可以同时执行多个操作。

             ② 可以一起执行许多操作,因此可以节省时间。(提高程序效率)

             ③ 线程是独立的,因此如果单个线程中发生异常,他不会影响其他线程。

     

    2.多任务处理

             多任务处理是同时执行多个任务的过程。使用多任务来利用CPU,多任务处理可以通过两种方式来实现:

             ① 基于进程的多任务处理(多进程)

                  特点:每个进程在内存中都单独分配有一个内存区域,进程是重量级的。进程之间的通信成本很高。从

                            一个进程切换到另一个进程需要一些时间来保存和加载寄存器、内存映射、更新列表等。

             ② 基于线程的多任务处理 (多线程)

                  特点:线程共享相同的地址空间;线程之间是轻量级的;线程之间的通信成本很低。

    3.Thread类

       java提供了Thread类来实现线程编程。Thread类提供了在线程上创建和执行操作的构造函数和方法。Thread类

       扩展了object类并实现了runnable接口。

       创建线程的方式: MyThread myThread = new MyThread();

    4.runnable接口

       创建线程有两种方式,一种是直接继承Thread类,另外一种是实现runnable接口。相比较Thread而言,通过实现

       runnable的方式可以更容易地实现资源共享,并且接口可以多实现且还能再继承其他类。

      总结:① 适合多个相同的程序代码的线程去处理同一个资源

                 ② 可以java中单继承的限制

                 ③ 增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

      创建线程的方式: MyThread myThread = new MyThread();     //只需要创建一个实例化对象然后被多个线程使用

                                   Thread Thread1 = new Thread(myThread);  //线程1

                                   Thread Thread2 = new Thread(myThread);  //线程2

     

      5.线程生命周期

                ① 新建状态:通过new创建一个线程,跟其他对象的创建时一样的。此时虚拟机会为其分配内存,并初始化

                                       其成员变量的值。

                ② 就绪状态:当线程对象调用了start方法之后,线程就进入了就绪状态。程序就会为其创建方法调用栈和程

                                       序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了,至于何时运

                                       行,取决于jvm中的线程调度器的调度。

                ③ 运行状态:当处于就绪状态的线程获得cpu,开始执行run()方法的线程执行体时,线程就进入了运行状态,

                                       线程调度的细节取决于底层平台采用的策略(抢占式调度策略和协作式调度策略)

                ④ 阻塞状态:运行状态的线程遇到以下情况就会进入阻塞状态:

                                      1.线程自己调用sleep方法主动放弃处理器资源;

                                      2.该线程调用了一个阻塞式IO方法,在该方法返回之前,该线程处于阻塞状态。

                                      3.该线程试图获得一个同步监视器,但该同步监视器正被其他线程持有。

                                      4.线程正在等待某个通知(notify)

                                      5.程序调用了线程的suspend方法,将线程挂起(容易导致死锁,避免使用)

               ⑤ 死亡状态:有三种情况会使线程进入死亡状态:

                                      1.run方法执行完成,线程正常结束。

                                      2.线程抛出未被捕获的exception或者error

                                      3.人为停止,比如调用stop方法(暴力停止,不建议使用),以及其他停止策略。

           

       6.线程中常用的方法

    package com.multithreading.test;
    
    //创建线程类,方法一
    public class MyThread extends Thread {
    	public MyThread() {
    		
    	}
    	public MyThread(String threadName,ThreadGroup tg) {
    		super(tg,threadName);
    		start();
    	}
    	//线程功能函数
    	public void run() {
    		for(int i=1;i<=5;i++) {
    			try {
    				Thread.sleep(500);
    			} catch (Exception e) {
    				System.out.println(e.toString());
    			}
    				System.out.println(Thread.currentThread().getName()+":"+i);
    			
    		}
    		
    	}
    	
    	
        public static void main(String[] args) throws InterruptedException {
        	
        	//创建线程的方式1
        	MyThread myThread = new MyThread();
        	myThread.start();
        	myThread.interruptAndIsInterruptedAndInterrupted();
        	
        	
        	
        	//创建线程的方式2
        	MyThread3 MyThread3 = new MyThread3();
        	
        	//线程1
        	Thread t1 = new Thread(MyThread3);
        		   t1.start();
            //线程2
            Thread t2 = new Thread(MyThread3);
        		   t2.start();
            
     
        	
        	
    	}
        
       	//1. start()  启动线程  线程方法
        public static void starts() {
        	MyThread myThread= new MyThread();
        	myThread.start();
        	
        }
        //2. run()  执行线程  线程方法
        public static void runs() {
        	
        	//开启线程之后,会自动运行run方法执行线程代码功能。如上上
        	MyThread myThread= new MyThread();
        	myThread.start();
        	
        }
        
        //3. sleep() 指定的时间内休眠线程
        public static void sleep() throws InterruptedException {
        	MyThread myThread= new MyThread();
        	myThread.start();
        	myThread.sleep(1000);   //休眠一秒钟(多线程中不会释放对象锁,与wait的比较)
        	
        }
        //4. currentThread()    返回对当前正在执行线程对象的引用   线程方法
        public static void currentThreads() {
        	MyThread myThread= new MyThread();
        	myThread.setName("我是MyThread");
        	myThread.start();
        	Thread t = Thread.currentThread();   //主线程
        	System.out.println(myThread.getName());
        	
        }
        //5. join()    实现线程的执行顺序  线程方法
        public static void joins() {
        	MyThread myThread1= new MyThread();
        	myThread1.setName("myThread1");
        	MyThread myThread2= new MyThread();
        	myThread2.setName("myThread2");
        	MyThread myThread3= new MyThread();
        	myThread3.setName("myThread3");
        	
        	myThread1.start();
        	try {
    			myThread1.join(1500);   //myThread1优先执行1500毫秒
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
        	myThread2.start();
        	myThread3.start();
        	
        }
        
        //6. setpriority()  设置线程优先级(1-10,默认为5,数字越大优先级越高,但不代表级别越高就一定优先执行,只是优先执行的概率更大)  
        //7. getPriority()  返回线程优先级级别
        //另外还有三个常规优先级属性   MIN_PRIORITY设置最小优先级,值为1     MAX_PRIORITY设置最大优先级,值为10   NORM_PRIORITY普通优先级值为5   
        public static void setPriorityAndGetPriority() {
        	MyThread myThread1= new MyThread();
        	MyThread myThread2= new MyThread();
        	
        	myThread1.setPriority(1);
        	myThread1.setName("myThread1");
        	System.out.println(myThread1.getPriority());
        	
        	myThread2.setPriority(9);
        	myThread2.setName("myThread2");
        	System.out.println(myThread2.getPriority());
        	
        	myThread1.start();
        	myThread2.start();
        	
        	//myThread1.setPriority(Thread.MIN_PRIORITY);
        	//myThread1.setPriority(Thread.MAX_PRIORITY);
        	//myThread1.setPriority(Thread.NORM_PRIORITY);
        	
        }
        
        //8. setName() 设置线程名称
        //9. getName() 获取线程名称
        public static void setNameAndGetName() {
        	//以上方法中已经多次应用
        }
    
        //返回线程编号
        public static void geId() {
        	MyThread myThread= new MyThread();
        	myThread.getId();
        	System.out.println(myThread.getId());
        }
        
        
        //19. isAlive()  测试线程是否活着  线程方法
        public static void isAlives() {
        	MyThread myThread= new MyThread();
        	myThread.start();
        	System.out.println(myThread.isAlive());  
        }
        
        //11. yield()      Thread类的yield()方法导致当前正在执行的线程对象暂停并允许其他线程执行(其实就是降低优先级,但不代表不会先执行)
        public static void yield() {
        	MyThread myThread1= new MyThread();
        	myThread1.setName("myThread1");
        	MyThread myThread2= new MyThread();
        	myThread2.setName("myThread2");
        	myThread1.start();
        	myThread2.start();
        	
        	for(int i=0;i<3;i++) {
        		//如果myThread1线程正在执行,则执行该方法,意味着自己不运行run,重新回到就绪状态与其他线程一同竞争cpu时间
        		myThread1.yield();
        		System.out.println(myThread1.getName()+":我们一同竞争吧");
        	}
             
        }
        
        //12. stop()   暴力停止线程,强制中断线程的执行。容易造成数据不一致,属于不安全的方法,包括suspend()(阻塞线程)  resume()(恢复线程) 等已经弃用
        public static void  stops() {
        	
        	//略
        	
        	
        }
        //13. destroy()    销毁线程组以及子线程组
        //ThreadGroup  线程组类,管理线程的类,即线程组就是由线程组成的管理线程的类,这个类是java.lang.ThreadGroup类
        public static void destroys() throws InterruptedException {
        	//创建一个名为Parent thread的线程组
        	ThreadGroup g1 = new ThreadGroup("Parent thread");  
        	
        	//创建一个名为Child thread的线程组
        	ThreadGroup g2 = new ThreadGroup("Child thread");  
        	
        	//在线程组中创建线程,在有参构造函数已经启动了线程
        	MyThread myThread1= new MyThread("myThread1",g1);
        	MyThread myThread2= new MyThread("myThread2",g2);
        	
        	
        	myThread1.join();
        	myThread2.join();
        	
        	g1.destroy();
        	System.out.println(g1.getName()+" is destoried");
        	
        	g2.destroy();
        	System.out.println(g2.getName()+" is destoried");
        }
        
        // 	14. isDaemon()  该线程是否是一个守护线程
        //  15. setDaemon() 将线程标记为守护线程或用户线程
        public static void  isDaemons() {
           	MyThread myThread= new MyThread();
        	
           	System.out.println(myThread.isDaemon());
           	
           	myThread.setDaemon(true);
           	
           	System.out.println(myThread.isDaemon());
           	//守护线程与用户线程(非守护线程)
           	//守护线程是为用户线程服务的,比如垃圾回收线程,非必要线程。当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程
           	//用户线程就是执行业务功能代码的线程。
           	
           	
        }
        
        //16. interrupt()      标记需要中断的线程,中断的执行由具体实现代码决定
        //17. isInterrupted()  用来判断当前线程的中断状态
        //18. interrupted()    此方法清除线程的中断状态,这意味着如果要连续两次调用此方法,则第二次调用将返回false。 如果线程的中断状态为true,则此方法将状态设置为false
        public  void interruptAndIsInterruptedAndInterrupted() {
        	MyThread2 myThread= new MyThread2();
          	
          	myThread.start();
          	
          	System.out.println(myThread.isAlive());
          	
          	myThread.interrupt();
        	System.out.println(myThread.isAlive());	
          	
        }
       
        
        class MyThread2 extends Thread{
        		
        	public void run() {
        		for(int i=1;i<=5;i++) {
        			try {
        				//为true时,说明被标记为需要中断的线程,然后通过return直接返回来实现中断线程
        			     if(Thread.currentThread().isInterrupted()) {
        			    	 return;
        			     }
        			} catch (Exception e) {
        				System.out.println(e.toString());
        			}
        				System.out.println(Thread.currentThread().getName()+":"+i);
        			
        		}
        		
        	}
        }
        
        
        //19. notify()    随机唤醒wait等待池中的线程,从而可以去竞争获取对象锁
        //20. notifyAll()  唤醒所有wait等待池中的线程
        public  static void notifyAndNotifyAll() {
        	
        	//略
        	
        }
        //21. wait  使线程进行阻塞状态,并且会释放锁
        public  static void waits() {
        	
        	//略
        	
        }
        
    }
    
    
    //创建线程方法2,实现rnnable接口
    class MyThread3 implements Runnable{
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		
    	}
    	
    }
    

    7.monitor(监视器)

        sychronized、wait、notify是任何对象都具有的同步工具。

       

        他们是应用于同步问题的人工线程调度工具。

        java中的每一个对象都有一个监视器来检测并发代码的重入。在非多线程编码时该监视器不发挥作用,反之如果在

        sychronized范围内,监视器发挥作用。

        wait/notify必须存在于sychronized块中。并且这三个关键字针对的是同一个监视器(某对象的监视器)。这意味着

        wait之后,其他线程就可以进入同步块执行。

        当某代码并不持有监视器的使用权时(如上图中5的状态,即脱离同步块)去wait或notify,会抛出java.lang.IllegalMo      
        nitorStateException。也包括在sychronized块中去调用另一个对象的wait/notify,因为不同对象的监视器不同,同样会

        抛出此异常。

         用法:

          sychronized单独使用:

          ① 代码块:如下,在多线程环境下,sychronized块中的方法获取lock实例的monitor,如果实例相同,那么只有一个线程

                         可以执行该代码块。

    public class Thread1 implements Runnable {
       Object lock;
       public void run() {  
           synchronized(lock){
             ..do something
           }
       }
    }

          ② 直接用于方法:相当于上面代码中用lock来锁定的效果,实际获取的是Thread1类的monitor。更进一步,如果修饰的

                                        是static方法,则锁定该类所有实例。

    public class Thread1 implements Runnable {
       public synchronized void run() {  
            ..do something
       }
    }
    
    

         sychronized、wait、notify结合:典型场景生产者消费者问题

         

    /**
       * 生产者生产出来的产品交给店员
       */
      public synchronized void produce()
      {
          if(this.product >= MAX_PRODUCT)
          {
              try
              {
                  wait();  
                  System.out.println("产品已满,请稍候再生产");
              }
              catch(InterruptedException e)
              {
                  e.printStackTrace();
              }
              return;
          }
    
          this.product++;
          System.out.println("生产者生产第" + this.product + "个产品.");
          notifyAll();   //通知等待区的消费者可以取出产品了
      }
    
      /**
       * 消费者从店员取产品
       */
      public synchronized void consume()
      {
          if(this.product <= MIN_PRODUCT)
          {
              try 
              {
                  wait(); 
                  System.out.println("缺货,稍候再取");
              } 
              catch (InterruptedException e) 
              {
                  e.printStackTrace();
              }
              return;
          }
    
          System.out.println("消费者取走了第" + this.product + "个产品.");
          this.product--;
          notifyAll();   //通知等待去的生产者可以生产产品了
      }

       volatile: https://blog.csdn.net/weixin_41690908/article/details/86771819

    8.高级多线程控制类  

             Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent,提供了大量高级工具,可以帮助开发者编写高效、

    易维护、结构清晰的Java多线程程序。       

      ①ThreadLocal类   

          用处: 保存线程的独立变量。对一个线程类(继承自Thread)
                      当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线

                      程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。常用于用户登录控制,如记录session

                     信息。

          实现:每个Thread都持有一个TreadLocalMap类型的变量(该类是一个轻量级的Map,功能与map一样,区别是桶里

                    放的是entry而不是entry的链表。功能还是一个map。)以本身为key,以目标为value。
          主要方法是get()和set(T a),set之后在map里维护一个threadLocal -> a,get时将a返回。ThreadLocal是一个特殊的容

          器。

      ②原子类(AtomicInteger、AtomicBoolean……)

          为八大基本数据类型配置了对应的原子类。。。

       ③lock类

          lock : 在java.util.concurrent包内。共有三个实现:

            ReentrantLock
            ReentrantReadWriteLock.ReadLock
            ReentrantReadWriteLock.WriteLock

                   主要目的是和synchronized一样, 两者都是为了解决同步问题,处理资源争端而产生的技术。功能类似但有

                   一些区别。      

            lock更灵活,可以自由定义多把锁的枷锁解锁顺序(synchronized要按照先加的后解顺序)
            提供多种加锁方案,lock 阻塞式, trylock 无阻塞式, lockInterruptily 可打断式, 还有trylock的带超时时间版本。
            本质上和监视器锁(即synchronized是一样的)
            能力越大,责任越大,必须控制好加锁和解锁,否则会导致灾难。
            和Condition类的结合。
            性能更高,对比如下图:

                   

                                     synchronized和Lock性能对比

            ReentrantLock

            可重入的意义在于持有锁的线程可以继续持有,并且要释放对等的次数后才真正释放该锁。
            使用方法是:

            先new一个实例       static ReentrantLock r = new ReentrantLock();

            加锁:r.lock()或r.lockInterruptibly();

                       两种加锁方式也是不同,后者可被打断。当a线程lock后,b线程阻塞,此时如果是lockinterruptibly,

                       那么在调用b.interrupt()之后,b线程退出阻塞,并放弃对资源的争夺,进入catch块(如果使用后者,

                       必须throw interruptable exception 或catch)  

            释放锁:r.unlock()

                           放在finally里面。以防止异常跳出了正常流程,导致灾难。这里补充一个小知识点,finally是可以

                           信任的:经过测试,哪怕是发生了OutofMemoryError,finally块中的语句执行也能够得到保证。

             ReentrantReadWriteLock  

             可重入读写锁(读写锁的一个实现)

        ReentrantReadWriteLock lock = new ReentrantReadWriteLock()
                ReadLock r = lock.readLock();
                WriteLock w = lock.writeLock();

             两者都有lock,unlock方法。写写,写读互斥;读读不互斥。可以实现并发读的高效线程安全代码。

    9.容器类

       这里就讨论比较常用的两个:BlockQueue和ConcurrentHashMap

        ① BlockQueue

             阻塞队列。该类是java.util.concurrent包下的重要类,BlockQueue是单向队列,可以在队列头部添加元素

             或者在队列尾部删除取出元素类似于一个管道,特别适用于先进先出策略的一些应用场景。普通的queue

             接口主要实现有PriorityQueue(优先队列)

             BlockingQueue在队列的基础上添加了多线程协作的功能:

            

             除了传统的queue功能(表格左边的两列)之外,还提供了阻塞接口put和take,带超时功能的阻塞接口offer

             和poll。put会在队列满的时候阻塞,直到有空间时被唤醒,take在队列空的时候阻塞,直到有东西可以被拿

             的时候才被唤醒。用于生产者-消费者模型尤其好用。

              常见的阻塞队列有:

               ArrayListBlockingQueue

               LinkedListBlockingQueue

               DelayQueue

               sychronizedBlockingqueue

          ② ConcurrentHashMap

               高效的线程安全哈希map。对比hashTable、concurrentHashMap、HashMap

    10.管理类

       管理类的概念比较范,用于管理线程,本身不是多线程的,但提供了一些机制来利用上述的一些工具做一些封装。

       值得一提的管理类:ThreadPoolExecutor和JMX框架下的系统级管理类ThreadMXBean。

       ThreadPoolExecutor 

    ExecutorService e = Executors.newCachedThreadPool();
        ExecutorService e = Executors.newSingleThreadExecutor();
        ExecutorService e = Executors.newFixedThreadPool(3);
        // 第一种是可变大小线程池,按照任务数来分配线程,
        // 第二种是单线程池,相当于FixedThreadPool(1)
        // 第三种是固定大小线程池。
        // 然后运行
        e.execute(new MyRunnableImpl());

      该类内部是通过ThreadPoolExecutor实现的,掌握该类有助于线程池的管理,本质上他们都是ThreadpoolExecutor

      类的各种实现版本。

    以上各参数:

    corePoolSize:池内线程初始值与最小值,就算是空闲状态,也会保持该数量线程。
    maximumPoolSize:线程最大值,线程的增长始终不会超过该值。
    keepAliveTime:当池内线程数高于corePoolSize时,经过多少时间多余的空闲线程才会被回收。回收前处于wait状态
    unit:
    时间单位,可以使用TimeUnit的实例,如TimeUnit.MILLISECONDS 
    workQueue:待入任务(Runnable)的等待场所,该参数主要影响调度策略,如公平与否,是否产生饿死(starving)
    threadFactory:线程工厂类,有默认实现,如果有自定义的需要则需要自己实现ThreadFactory接口并作为参数传入。

     

       

             

      

     

      

          

                

     

    展开全文
  • 多线程面试题(值得收藏)

    万次阅读 多人点赞 2019-08-16 09:41:18
    史上最强多线程面试47题(含答案),建议收藏 金九银十快到了,即将进入找工作的高峰期,最新整理的最全多线程并发面试47题和答案总结,希望对想进BAT的同学有帮助,由于篇幅较长,建议收藏后细看~ 1、并发编程三要素?...
  • 初始多线程

    2021-04-25 10:22:22
    概念 进程:系统分配资源的最小单位 线程:系统调度资源的最小单位,被包含在...线程的数量不是越多越好,当线程的数量达到某个合适的值是最好的,如果有太多的线程,会出现线程之间的争夺和CPU的过度调度问题,而CPU
  • 多线程编程 - 单线程和多线程执行对比 递归求斐波那契、阶乘与累加函数的执行。该脚本按照单线程的方式运行这三个函数,之后使用多线程...因为我们希望让 MyThread 类越通用越好 (有输出和没有输出的调用都能够执行...
  • 系统环境Ubuntu 16.04 ServerPython3.5爬虫情况1、从Mysql数据库获取任务2、任务导入列表后开始http请求,将数据以文件形式保存到硬盘3、开80线程遇到的问题1、家用路由器频繁死机(一天两三次)2、爬虫开始时爬取...
  • java多线程

    2017-10-25 16:29:47
    前言java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多、越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的。这篇文章主要是对多线程的问题进行总结的,...
  • 多进程与多线程区别

    万次阅读 多人点赞 2016-04-21 10:01:16
    在Unix上编程采用多线程还是多进程的争执由来已久,这种争执最常见到在C/S通讯中服务端并发技术 的选型上,比如WEB服务器技术中,Apache是采用多进程的(perfork模式,每客户连接对应一个进程,每进程中只存在唯一一...
  • Java多线程

    千次阅读 多人点赞 2019-05-04 22:28:49
    一、多线程的概念 想要知道什么是多线程?就会引出线程的概念,而线程和进程之间又是息息相关的。 进程:操作系统中一个程序的执行周期称为一个进程。 线程:一个程序同时执行多个任务。通常,每一个任务就称为...
  • 求一个C#多线程的源码。越简单越好。要能够体现出多线程比单线程效率高
  • 码农小光关注 72020.04.18 00:04:50字数 3,178阅读 9,004 来源公众号:于日拱一兵 作者:tan日拱一兵 你有一个思想,我有一个思想,我们交换后,一个人就有两个...既然多线程编程容易出错,为什么它还经久不...
  • JAVA线程与多线程

    千次阅读 多人点赞 2016-08-25 19:10:10
    去安卓面试的时候通常会问一些java问题,所以呢你可能觉得答问题时...多线程的运行是根据CPU切换完成,如何切换由CPU决定,因此多线程运行具有不确定性。● 线程java中的线程使用java.lang.Thread类或者java.lang.Ru
  • 异步多线程

    千次阅读 2017-11-23 21:11:32
    1.首先讲解一下进程、线程与多线程的概念 进程-线程 计算机概念 进程是一个程序在电脑上运行时,全部计算资源的合集叫进程。 线程是程序的最小执行单位,包含计算资源,任何一个操作的响应都是线程。 多线程:多个...
  • 电话面试的面试题,有一个线程负责读取任务数据放到内存队列,现在开了50个线程做任务处理,然后面试官就问任务处理线程是否越多越好,不考虑内存限制,也不考虑线程间的资源争夺。这道题更像是开放性的题目,我能...
  • 重点将关注如何在实际项目中更好的使用多线程,因为我相信可能有很多项目中可能并不需要我们使用多线程,或者说开发人员并没有注意到可以使用多线程,其次多线程也并不是创建的越多越好,再加上共享资源下线程安全,...
  • 多线程的理解

    2020-10-29 18:16:08
    文章目录1 多线程2线程是不是越多越好?2.1 例子说明2.2 原因:3 线程池往下看 1 多线程 2线程是不是越多越好? 2.1 例子说明 启动: 查看运行情况: 2.2 原因: 3 线程池 往下看 ......
  • C# 多线程

    万次阅读 多人点赞 2019-05-29 17:56:35
    一、基本概念 1、进程 首先打开任务管理器,查看当前运行的进程: 从任务管理器里面可以看到当前所有正在运行的进程。...线程是操作系统分配处理器时间的基本单元,在进程中可以有线程同时执行代码。进...
  • Java多线程面试题

    万次阅读 2020-10-25 15:56:40
    sleep 方法: 是 Thread 类的静态方法,当前线程将睡眠 n 毫秒,线程进入阻塞状态。当睡眠时间到了,会解除阻塞,进行可运行状态,等待 CPU 的到来。睡眠不释放锁(如果有的话); wait 方法: 是 Object 的方法...
  • Java 多线程通信

    千次阅读 2018-10-14 10:52:47
    然而,并不是启动越多线程,就能让程序执行快,多线程同时带来了上下文切换、多线程间的通信与同步、死锁等问题。合理的利用多线程进行编程是一件有挑战性的事。 Java自一开始就内置了对多线程的支持,在JDK1.5...
  • 我说我懂多线程,面试官立马给我发了offer

    万次阅读 多人点赞 2020-04-07 09:24:52
    多线程不是银弹,并不是说线程越多,我们的资源利用效率就越好。执行IO操作我们线程可以适当多一点,因为很多时候CPU是相对空闲的。如果是计算型的操作,本来CPU就不空闲了,还开很多的线程就不对了(有多线程就会...
  • 多线程多少算多?

    2017-11-17 09:39:43
    最近在抓软件的性能优化。...那么,是不是线程越多越好呢? 假设我们有100个下载任务,我们可以有以下3种实现方法: 使用一个线程,依次执行100个下载任务;使用100个线程,每个线程执行一个下
  • Java - 多线程

    万次阅读 2019-03-23 10:43:55
    分享一个大牛的人工智能教程。零基础!通俗易懂!...用多线程只有一个目的,那就是更的利用CPU的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应”多角色”的程序...
  • Python 线程 多线程 线程池

    千次阅读 2018-08-24 13:56:16
    多线程, 线程池测试: Python 使用多线程,有两种方式:函数,或者用类来包装线程对象。 现在有一个需求:如下图,我们需要把test.jpg 复制5000次到update文件夹下面。并且在复制过程中需要重命名,命名规则为 ...
  • linux多线程

    2015-02-26 15:02:12
    线程,有时候被称为轻量级进程(light weight ...(这里是从并发的角度考虑的,对于单核CPU,某一时刻只会有一个线程再执行),一个线程阻塞了并不会影响另一个线程,多线程的进程尽可能的利用系统CPU资源。对于一

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 186,645
精华内容 74,658
关键字:

多线程是不是越多越好