• Nenhum resultado encontrado

6.7 • Escalonamento de threads Java

No documento [PT] SILBERSCHATZ - Sistemas Operacionais (páginas 132-135)

A JVM escalona threads usando um algoritmo de escalonamento preemptivo baseado em prioridades. Todos os threads Java recebem uma prioridade e a JVM escalona o thread executável com a prioridade mais alta para execução. Se dois ou mais threads executáveis tiverem a prioridade mais alta, a JVM escalonará os thre- ads usando uma fila FIFO.

A JVM escalona um thread para execução quando um dos seguintes eventos ocorre:

1. O thread em execução no momento sai do estado Executável. Um thread pode deixar o estado Execu- tável de várias formas, tais como bloqueando operações de l/O, saindo do seu método run( ) ou cha- mando o método suspendi ) ou stop{ ).

2. Um thread com prioridade mais alta do que o thread em execução no momento entra no estado Exe- cutável. Nesse caso, a JVM interrompe o thread em execução no momento e escalona o thread com prioridade mais alta para execução.

6.7.1 Fatia de tempo

A especificação da JVM não indica se os threads têm ou não fatias de tempo - isso cabe à implementação especí- fica da JVM. Se os threads tiverem fatias de tempo, um thread Executável será executado durante seu quantum de tempo ou até sair do estado Executável ou ser interrompido por um thread de prioridade mais alta. Se os threads não tiverem fatia de tempo, um thread será executado até que um de dois eventos listados ocorra.

De modo que todos os threads tenham uma quantidade igual de tempo de CPU em um sistema que não realiza fracionamento de tempo, um thread poderá passar o controle da CPU com o método yield( ). Ao chamar o método yi el d ( ), um thread abandona o controle da CPU permitindo que outro thread de priori- dade igual seja executado. Quando um thread voluntariamente cede o controle da CPU temos o que se chama de multitarefa cooperativo. O uso do método yield( ) aparece como

public void run( ) { while (true) {

112 • Sistemas Operacionais

// realiza uma tarefa de uso intensivo da CPU

// passa o controle da CPU Thread.yield( )

)

I

6.7.2 Prioridades de thread

Conforme mencionado, a JVM escalona threads de acordo com a prioridade. A JVM seleciona executar um thread Executável com a prioridade mais alta. Todos os threads Java recebem como prioridade um inteiro positivo dentro de um determinado intervalo. Os threads recebem uma prioridade default quando são cria- dos e - a menos que sejam alterados explicitamente pelo programa - eles mantêm a mesma prioridade em toda sua vida; a JVM não altera prioridades de forma dinâmica. A classe Thread de Java identifica as seguintes prioridades de thread:

Prioridade Comentário Thread.N0RM_PR10RITY A prioridade default de thread.

Thread.MIN_PRIORITY A prioridade mínima de thread. Thread.MAX_PRIORITY A prioridade máxima de thread.

O valor de MINPRIORITY é 1, o de MAX_PRIORITY é 10 e o de N0RM_PR10R1TY é 5. Todo thread Java tem uma prioridade que se encaixa nesse intervalo. Quando um thread é criado, recebe a mesma prioridade que o thread que o criou. A menos que especificado de outro modo, a prioridade default para todos os threads é N0RM_PRI0RITY. A prioridade de um thread também pode ser definida explicitamente com o método setPri o- r i t y ( ). A prioridade pode ser definida antes de um thread ser iniciado ou enquanto um thread está ativo. A classe HighThread (Figura 6.10) aumenta a prioridade em 1 a mais do que a prioridade default antes de execu- tar o restante do seu método run( ).

public class

\

public void run( ) {

this.setPrioHty(Thread.NORM_PRIORITY t 1); // restante do método run( )

Figura 6.10 Definindo uma prioridade usando setPriority( ). 6 . 7 . 3 E s c a l o n a d o r R o u n d - R o b i n c o m b a s e e m J a v a

A classe Schedul er (Figura 6.11) implementa um escalonador de threads circular com fatias de tempo. O es- calonador contém uma única fila de threads da qual seleciona um thread para execução. O escalonador executa como um thread separado com prioridade 6. Os threads que ele escalona têm prioridade 2 ou 4, dependendo se o thread foi ou não escalonado para executar.

A operação do escalonador é a seguinte: quando um thread é adicionado à fila do escalonador (com o método addThreadf )), recebe a prioridade default 2. Quando o escalonador seleciona um thread para exe- cutar, ele define a prioridade do thread para 4. O escalonador então 6 suspenso por um quantum de tempo. Como a JVM usa o algoritmo de escalonamento baseado em prioridade, o thread com a prioridade 4 é o thread Executável de prioridade mais alta, por isso recebe a CPU pelo quantum de tempo. Quando o quan- tum expira, o escalonador é reativado. Como o escalonador está executando na prioridade 6, ele interrom- pe o thread em execução no momento. O escalonador define, então, a prioridade do thread interrompido novamente para 2 e seleciona um novo thread para execução, repetindo o mesmo processo.

escalonamento de CPU • 113 Se não houver threads na fila, o escalonador entra em um laço esperando para recuperar o próximo thre- ad. Em geral, laços de espera ocupada representam um desperdício dos recursos da CPU. No entanto, prova- velmente não importa nesse caso, já que não existem threads disponíveis para execução além do escalonador. Assim que outro thrcad esiivcr pronto para executar, o escalonador o escalonará e será suspenso. Uma modi- ficação bem simples na classe Ci reul arU st é acrescentar o método 1 sEmpty ( ) que indica ao escalonador se a fila está vazia ou não. Se a fila estiver vazia, o escalonador poderá ser suspenso durante algum tempo e, cm se- guida, reativado para verificar a fila novamente. Tal modificação evita a atividade de espera ocupada do esca- lonador.

A classe TestSchedul er (Figura 6,12) ilustra como o escalonador pode ser usado criando uma instância do mesmo e adicionando três threads à sua fila. C o m o o fracionamento do tempo n ã o pode ser presumido, a classe TestSchedul er está executando com a prioridade mais alta para que continue executando a fim de ini- ciar todos os threads.

public class Scheduler extends Thread {

public Scheduler( ) {

tlmeSHce « DEFAUtJ_TIHE_SLlCE; queue = new C 1 r c u l a r l i s t ( ); »

public Scheduler(int quantura) ( timeSlice • quantum;

queue • new C i r c u l a r L i s t ( );

1

public void addThread(Thread t) { t . s e t P r i o r i t y ( 2 ) ; queue.additem(t); I p r i v a t e void $chedulerSleep( ) { try { Thread.sieepítimeSlice); } catch (InterruptException e) ( }; )

public void run( ) { Thread current; t h i s . s e t P r i o r i t y ( 6 ) ; while ( t r u e ) {

// obtém o próximo thread

current • (Thr&ad)queue.getNetx{ ); if ( ( current !« n u l l ) && ( c u r r e n t . i s A l i v e ( )) ) { c u r r e n t . s e t P r i o r i t y ( 4 ) ; schedulerSleçp( ); c u r r e n t . s e t P r l o r l t y ( 2 ) ;

1

) ) p r i v a t e C i r c u l a r L i s t queue; private i n t timeSlice; p r i v a t e s t a t i c f i n a l i n t DEFAUUTIME SLICE » 1000;

I

114 • Sistemas Operacionais

No documento [PT] SILBERSCHATZ - Sistemas Operacionais (páginas 132-135)

Outline

Documentos relacionados