import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class PriorityQueue< T >{ /** Main lock guarding all access */ final ReentrantLock lock = new ReentrantLock( ); /** Condition for waiting takes */ private final Condition notEmpty = lock.newCondition( ); /** Condition for waiting puts */ @SuppressWarnings ( "unused" ) private final Condition notFull = lock.newCondition( ); private final AtomicInteger count = new AtomicInteger( ); private List< Queue< T > > lbqList; private int capacity; private Priority< T > priority; private boolean queue; public PriorityQueue( int capacity , Priority< T > priority , boolean queue ) { this.capacity = capacity; this.priority = priority; this.queue = queue; init( ); } private void init( ) { lbqList = new ArrayList<>( this.capacity ); for ( int i = 0 ; i < capacity ; i++ ) { if ( queue ) { lbqList.add( new LinkedList<>( ) ); } else { lbqList.add( new LinkedBlockingQueue<>( ) ); } } } public int add( T t ) throws Exception { int pr = priority.getPriority( t ); Queue< T > queue = lbqList.get( pr ); if ( count.get( ) > 0 ) { count.getAndIncrement( ); queue.add( t ); if ( count.get( ) <= 1 ) { final ReentrantLock lock = this.lock; try { lock.lockInterruptibly( ); notEmpty.signal( ); } catch ( Exception e ) { return -1; } finally { lock.unlock( ); } } } else { final ReentrantLock lock = this.lock; try { lock.lockInterruptibly( ); queue.add( t ); count.getAndIncrement( ); notEmpty.signal( ); return pr; } catch ( Exception e ) { throw e; } finally { lock.unlock( ); } } return pr; } public T get( ) throws InterruptedException { T t; if ( count.get( ) > 0 ) { t = getData(); if(t != null){ return t; } } final ReentrantLock lock = this.lock; lock.lock( ); try { while ( ( t = getData( ) ) == null ) notEmpty.await( ); return t; } finally { lock.unlock( ); } } public static interface Priority< T > { int getPriority( T t ); } public T getData(){ int i = 0; T t; for( ; ;){ t = lbqList.get( i++ ).poll( ); if( t != null){ count.getAndDecrement( ); return t; } if( i >= capacity ){ return null; } } } public int size( ) { return count.get( ); } public boolean isEmpty( ) { return count.get( ) == 0; } }
test代码
@Test public void testQ( ) throws InterruptedException { Priority< Notification > priority = new Priority< Notification >( ) { @Override public int getPriority( Notification t ) { return t.getPriority( ); } }; PriorityQueue< Notification > rq = new PriorityQueue<>( 6 , priority , false ); ThreadPoolExecutor te = new ThreadPoolExecutor( 8 , 8 , 100 , TimeUnit.MICROSECONDS , new LinkedBlockingQueue< Runnable >( ) ); ThreadPoolExecutor ted = new ThreadPoolExecutor(4 , 4 , 100 , TimeUnit.MICROSECONDS , new LinkedBlockingQueue< Runnable >( ) ); int sum = 100; int read = sum , write = sum; boolean boo = true; AtomicLong at = new AtomicLong( ); for ( ; ; ) { int i = rr.nextInt( 10 ); if ( boo && read > 0) { for (int j = 0 ; i >= j ; j++ ) { te.execute( new Runnable( ) { @Override public void run( ) { try { Notification nf = new Notification( ); nf.setId( at.getAndIncrement( ) ); //nf.setPriority( r.nextInt( 6 ) ); nf.setPriority( nf.getId( )%30==0?5:1 ); rq.add( nf ); System.out.println( String.format( " read tid : %d data : %s" ,Thread.currentThread( ).getId( ) , nf ) ); } catch ( Exception e ) { e.printStackTrace( ); } } } ); } read = read - i; boo = !boo; } else if( !boo && write > 0){ for ( int j = 0 ; i >= j ; j++ ) { ted.execute( new Runnable( ) { @Override public void run( ) { try { Notification nf = rq.get( ); System.out.println( String.format( " write tid : %d data : %s" ,Thread.currentThread( ).getId( ) , nf ) ); } catch ( InterruptedException e ) { // TODO 自动生成的 catch 块 e.printStackTrace( ); } } } ); } boo = !boo; write = write - i; } if ( read <= 0 && write <= 0 ) { break; } if( read <= 0){ boo = false; } if( write <= 0 ){ boo = true; } } System.out.println( "---------------------------------------------------------------------" ); Thread.sleep( 1000000000 ); }