<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      java節拍器 定時任務 ScheduledExecutorService 記錄

      java節拍器 定時任務 ScheduledExecutorService 總結

      起因

      明明干啥都是個小菜雞,還那么多事事。是這樣的,想學吉他,手機上的節拍器軟件嫌聲音小,電腦上沒仔細找好用的節拍器,但是電腦有音箱,也用電腦看譜子練練啥的,就想有個電腦好用的節拍器。

      簡介

      從網上復制了一個播放WAV的代碼, 播放WAV的聲音。

      使用ScheduledExecutorService 來定時任務。

      掉進了很多坑

      先用多線程,會卡。

      又用線程池,還是會卡。

      查了資料可以用ScheduledExecutorService ,為了學習,先用了Timer和TimerTask,慢的速度可以,快速就不行。

      最后用了ScheduledExecutorService。

      還有個極大的坑,那就是我剛開始一直連接的藍牙音箱,速度快多線程,線程池都不卡,慢的時候有時候會有拍子不響,真是奇了怪。可是巧了,誤打誤撞,最后用ScheduledExecutorService 的時候,用的筆記本自帶揚聲器,很順利,然后連上了藍牙音箱,速度慢音箱放的聲音會卡。卡不卡和播放設備很有關系。就試了之前用的線程那些方法,果然還是卡,用ScheduledExecutorService 就對了。

      多線程

      將寫一個播放的類,繼承Thread或者實現Runnable接口,然后

      while(true) {   //diPath, rate  文件路徑和延時時間
      			Thread thread1 = new Thread(new MyPlayer(new FileInputStream(diPath)));
      			Thread thread2 = new Thread(new MyPlayer(new FileInputStream(daPath)));
      			Thread thread3 = new Thread(new MyPlayer(new FileInputStream(daPath)));
      			Thread thread4 = new Thread(new MyPlayer(new FileInputStream(daPath)));
      			thread1.start();
      			Thread.sleep(rate);
      			thread2.start();
      			Thread.sleep(rate);
      			thread3.start();
      			Thread.sleep(rate);
      			thread4.start();
      			Thread.sleep(rate);
      		}
      }

      沒有想到別的辦法,在循環里每次創建。這很垃圾,我也知道。

      線程池

      用線程池,理論效果應該減少了系統的開銷,可是實際上沒有效果。

      思路還是剛剛的思路就是用了線程池,還是垃圾代碼。

      ThreadPoolExecutor tpool = new ThreadPoolExecutor(16, 20, 1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
      while (true) {   //diPath, rate  文件路徑和延時時間
          tpool.execute(new MyPlayerSu(diPath));
      	Thread.sleep(rate);
      	tpool.execute(new MyPlayerSu(daPath));
      	Thread.sleep(rate);
      	tpool.execute(new MyPlayerSu(daPath));
      	Thread.sleep(rate);
      	tpool.execute(new MyPlayerSu(daPath));
      	Thread.sleep(rate);
      }

      Timer和TimerTask

      使用方法,創建一個類繼承TimerTask,和繼承線程類差不多,然后重寫里面的run()方法,然后創建Timer對象,調用相應的方法,傳入相關對象和數值,也可以使用匿名對象。

      Timer timer = new Timer();// 實例化Timer類
      timer.scheduleAtFixedRate(new TimerTask() {
      		public void run() {
                      //代碼
               },xx,xx)

      Timer有兩個主要的運行方法,schedulescheduleAtFixedRate,有細微差距。schedulescheduleAtFixedRate方法一般情況下是沒什么區別的,只在某個情況出現時會有區別--當前任務沒有來得及完成下次任務又交到手上。

      我們來舉個例子:

      暑假到了老師給schedule和scheduleAtFixedRate兩個同學布置作業。
      老師要求學生暑假每天寫2頁,30天后完成作業。
      這兩個學生每天按時完成作業,直到第10天,出了意外,兩個學生出去旅游花了5天時間,這5天時間里兩個人都沒有做作業。任務被拖延了。
      這時候兩個學生采取的策略就不同了:
      schedule重新安排了任務時間,旅游回來的第一天做第11天的任務,第二天做第12天的任務,最后完成任務花了35天。
      scheduleAtFixedRate是個守時的學生,她總想按時完成老師的任務,于是在旅游回來的第一天把之前5天欠下的任務以及第16天當天的任務全部完成了,之后還是按照老師的原安排完成作業,最后完成任務花了30天。

      用Timer這個方法,太快了的時候,滴答的聲音會播放不完,從而會繼續等播放結束后才能播放下一個聲音,所以假如聲音時間長,或者太快就會不準了。

      ScheduledExecutorService 代替Timer

      ExecutorService可以調度命令在給定的延遲之后運行,或定期執行。 詳解去百度,百度上用一些。

      創建ScheduledExecutorService

      ScheduledExecutorService service = Executors.newScheduledThreadPool(10);

      使用的話,有三個方法schedulescheduleAtFixedRatescheduleWithFixedDelay

      • schedule(Callable<V> callable, long delay, TimeUnit unit) 創建并執行在給定延遲后啟用的ScheduledFuture。
      • schedule(Runnable command, long delay, TimeUnit unit) 創建并執行在給定延遲后啟用的單次操作。
      • scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) 創建并執行在給定的初始延遲之后,隨后以給定的時間段首先啟用的周期性動作; 那就是執行將在initialDelay之后開始,然后是initialDelay+period ,然后是initialDelay + 2 * period ,等等。
      • scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) 創建并執行在給定的初始延遲之后首先啟用的定期動作,隨后在一個執行的終止和下一個執行的開始之間給定的延遲。

      看方法描述,用scheduleAtFixedRate,傳入的runnable會自己循環運行,就傳入一次就行。

      我先用循環創建幾個Thread對象

      /**
       * @param di 滴的文件路徑
       * @param da 噠的文件路徑
       * @param patNum 一小節響幾次
       * @return 創建的播放聲音的線程數組
       */
      public Thread[] getThread(String di, String da, int patNum) {
      		Thread[] threads = new Thread[patNum];
      		threads[0] = new Thread(new MyPlayerWAV(di));
      		for (int i = 1; i < threads.length; i++) {
      			threads[i] = new Thread(new MyPlayerWAV(da));
      		}
      		return threads;
      	}

      然后,創建對象,傳入數值,執行方法就OK

      PalyerPat palyer = new PalyerPat();
      Thread[] threads = palyer.getThread(diPath, daPath, patNum);
      ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
      for (int i = 0; i < threads.length; i++) {
      	service.scheduleAtFixedRate(threads[i], rate * i, rate * patNum, TimeUnit.MILLISECONDS);
      }//rate * i 頭一次響的開始時間
      //rate * patNum 延時多久。響一次需要延時一小節。

      播放WAV方法

      java原生就支持,不用第三方。(copy大佬的)

      import java.io.*;
      import java.util.concurrent.*;
      import javax.sound.sampled.*;
      
      public void player(String filename) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
      		AudioInputStream stream;
      		stream = AudioSystem.getAudioInputStream(new File(filename));
      		AudioFormat target = stream.getFormat();
      		DataLine.Info dinfo = new DataLine.Info(SourceDataLine.class, target);
      		SourceDataLine line = null;
      		int len = -1;
      		line = (SourceDataLine) AudioSystem.getLine(dinfo);
      		line.open(target);
      		line.start();
      		byte[] buffer = new byte[1024];
      		while ((len = stream.read(buffer)) > 0) {
      			line.write(buffer, 0, len);
      		}
      		line.drain();
      		line.stop();
      		line.close();
      		stream.close();
      	}

      播放mp3

      需要包mp3spi。
      maven依賴

      <dependency>
      		<groupId>com.googlecode.soundlibs</groupId>
      		<artifactId>mp3spi</artifactId>
      		<version>1.9.5.4</version>
      </dependency>
      Player player;
      player = new Player(new FileInputStream(filename));//網上的代碼外面還有一層BufferedInputStream,當時找播放卡的問題看了源碼,原理里面有創建一個BufferedInputStream,我就省掉了。
      player.play();

      如果用這個播放,會卡,還是卡,啊,剛剛試了一下,原因以后再找。這只是播放的,在節拍器中會卡的。原來還是有坑。坑太多了。

      end

      非音樂專業,不專業,勿吐槽。非大佬,小菜雞一只,望大佬指點。

      更新一下,播放MP3卡不卡,和聲音文件也有關系,把之前用WAV文件轉成了MP3,是不會卡的,之前的MP3是我從一段音頻中截出來的,可能太粗糙了,造成了這樣的原因。現在所用的WAV音頻,是從手機安裝包中偷的,很nice。

      附上全部代碼

      import java.io.File;
      import java.io.IOException;
      import java.util.concurrent.*;
      
      import javax.sound.sampled.*;
      
      public class PalyerPat {
      
      	public static void main(String[] args) {
      		String diPath = "src/main/resources/tone1.wav";
      		String daPath = "src/main/resources/tone1_1.wav";
      		int patNum = 4;
      		int speed = 160;//輸入的速度
      
      		int rate = (int) (60F / speed * 1000);//轉成每響一次延時的毫秒。
      		PalyerPat palyer = new PalyerPat();
      
      		Thread[] threads = palyer.getThread(diPath, daPath, patNum);
      		ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
      		
      		for (int i = 0; i < threads.length; i++) {
      			service.scheduleAtFixedRate(threads[i], rate * i, rate * patNum, TimeUnit.MILLISECONDS);
      		}
      
      	}
      /**
       * @param di 滴的文件路徑
       * @param da 噠的文件路徑
       * @param patNum 一小節響幾次
       * @return 創建的播放聲音的線程數組
       */
      	public Thread[] getThread(String di, String da, int patNum) {
      		Thread[] threads = new Thread[patNum];
      		threads[0] = new Thread(new MyPlayerWAV(di));
      		for (int i = 1; i < threads.length; i++) {
      			threads[i] = new Thread(new MyPlayerWAV(da));
      		}
      		return threads;
      	}
      }
      
      class MyPlayerWAV implements Runnable {
      
      	String filename = "src/main/resources/tone1.wav";
      
      	public MyPlayerWAV() {
      	}
      
      	public MyPlayerWAV(String filename) {
      		super();
      		this.filename = filename;
      	}
      
      	public void run() {
      		try {
      			playerWAV(filename);
      //			System.out.println(filename);
      		} catch (UnsupportedAudioFileException e) {
      			e.printStackTrace();
      		} catch (IOException e) {
      			e.printStackTrace();
      		} catch (LineUnavailableException e) {
      			e.printStackTrace();
      		}
      	}
      
         	//播放WAV文件方法
      	public void playerWAV(String filename) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
      		AudioInputStream stream;
      		stream = AudioSystem.getAudioInputStream(new File(filename));
      		AudioFormat target = stream.getFormat();
      		DataLine.Info dinfo = new DataLine.Info(SourceDataLine.class, target);
      		SourceDataLine line = null;
      		int len = -1;
      		line = (SourceDataLine) AudioSystem.getLine(dinfo);
      		line.open(target);
      		line.start();
      		byte[] buffer = new byte[1024];
      		while ((len = stream.read(buffer)) > 0) {
      			line.write(buffer, 0, len);
      		}
      		line.drain();
      		line.stop();
      		line.close();
      		stream.close();
      	}
      }
      

      posted on 2021-02-12 21:26  寄居の友人c  閱讀(137)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 亚洲日韩一区二区| 亚洲国产在一区二区三区| 中文字幕无码av激情不卡| 日韩亚洲精品国产第二页| 小嫩模无套内谢第一次| 久久综合88熟人妻| 日韩乱码视频一区二区三区| 亚洲精品动漫免费二区| 艳妇臀荡乳欲伦69调教视频| 亚洲肥熟女一区二区三区| 乱妇乱女熟妇熟女网站| 中文字幕乱码在线播放| 亚洲精品一区三区三区在| 国产a在亚洲线播放| 肉大捧一进一出免费视频| 国产成人片无码视频| 国产系列丝袜熟女精品视频| 五月综合激情婷婷六月| 一个色综合色综合色综合| 亚洲第一香蕉视频啪啪爽| 波多野结衣久久一区二区| 在线a亚洲老鸭窝天堂| 久久久综合九色合综| 深夜福利成人免费在线观看| VA在线看国产免费| 玩弄丰满少妇人妻视频| 久久国内精品一区二区三区| 天天看片视频免费观看| 国产在线观看免费观看| 欧美人与性动交α欧美精品| 亚洲成人av一区二区| 欧美不卡无线在线一二三区观| 克什克腾旗| 国产精品va在线观看h| 亚洲一区二区三级av| 成在线人视频免费视频| 国产精品福利午夜久久香蕉| 中文国产日韩欧美二视频| 国产av黄色一区二区三区| 亚洲一区二区精品另类| 欧美人与禽2o2o性论交|