2015-05-07 4 views
1

Я делаю несколько экспериментов, чтобы попытаться понять Threads на практике. Посмотрите на следующий фрагмент: это функция main, которая запускает поток, прослушивающий порт 2020. Этот поток, в свою очередь, прослушивает подключения на этом порту, и, когда клиент подключается, он порождает еще один поток, который немного спит а затем записывается в сокет.Смешное поведение темы в Scala

class MyRunner(s:Socket,num:Int) extends Runnable{ 

    val r = scala.util.Random 

    def run(): Unit ={ 

    if(num == 5) 
     Thread.sleep(15000) 
    else 
     Thread.sleep(1000) 

    s.getOutputStream.write(s"My number is ${num}! \n".getBytes) 
    s.getOutputStream.close() 
    } 
} 

// this thread opens a MyRunner thread on each new connection 
class MyService extends Runnable{ 

    val serverSocket = new ServerSocket(2020) 

    var num = 0 

    def run():Unit = { 
    while(true){ 
     val socket = serverSocket.accept() 
     num += 1 
     (new MyRunner(socket,num)).run() 
    } 
    } 
} 

// main function 
object app { 
    def main(args: Array[String]) { 
    (new MyService).run 
    } 
} 

Теперь я тестирую эту установку. Вот что я сделал: я открыл два окна терминала, и на каждом из них я вошел в команде:

$ for i in `seq 1 5`; do netcat localhost 2020; done 

вещи, когда число 5 достигается (в соответствии с условным) на одном из терминалов, другой один не продолжается. Оба клиента останавливаются до завершения 15-секундного таймаута.

Я хотел бы знать, что я делаю неправильно, потому что я думал, что вся цель использования потоков состояла в том, чтобы иметь неблокирующие приложения, которые могут обслуживать клиента, даже если другой занят.

P.S .: Я запускаю это на виртуальной виртуальной машине с 4 доступными процессорами (от общего числа 8 на моей главной машине).

ответ

7

Ваше приложение не создает ниток. Создать поток, как это:

Thread serverThread = new Thread(new MyService()); 
serverThread.start(); 

thread.start() является методом низкого уровня, который обеспечивается библиотекой для вашего кода, чтобы позвонить, если вы хотите, чтобы создать новую тему.

serverThread.run() является метод, который код обеспечивает для библиотеки позвонить в новой нити.


Extra Credit: Узнайте, как использовать пул потоков (например, java.util.concurrent.ThreadPoolExecutor) вместо того, чтобы создавать и уничтожать новый поток для каждого клиентского соединения. Создание и уничтожение потоков дорого.

+0

Да. Я знал, что что-то понял. Благодарю. –

+0

У вас есть хороший источник, где вы можете узнать о ThreadPoolExcecutor? – Shondeslitch

+2

@Shondeslitch, глава «параллелизма» в стандартном учебнике Java, вероятно, является хорошим местом для начала: https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html –

Смежные вопросы