# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + colab={} colab_type="code" id="58OiOlTxMvwh"
#concorrência - Códigos adaptados de [FORBES, Elliot. Learning Concurrency in Python: Build highly efficient, robust, and concurrent applications. 2017.]

# + colab={"base_uri": "https://localhost:8080/", "height": 34} colab_type="code" executionInfo={"elapsed": 955, "status": "ok", "timestamp": 1597495270821, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="e1YSKJBIjvwL" outputId="29836548-ac45-4d4e-9ad2-18fabe20d2cd"
#identificando a quantidade de núcleos disponíveis para o sistema
import multiprocessing
multiprocessing.cpu_count() #conta a quantidade de núcleos disponíveis no sistema 

# + colab={"base_uri": "https://localhost:8080/", "height": 204} colab_type="code" executionInfo={"elapsed": 13610, "status": "ok", "timestamp": 1597495628883, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="9QLPusRsmAvV" outputId="96d182f6-68c1-455a-9aa6-8f496e595681"
#processamento sequencial
import threading  #módulo para a construção de threads
import urllib.request  #módulo para a requisição de url
import time  #módulo para tratar tempo

#função criada para a realização do download das imagens
def downloadImagens(imagePath, fileName):
  print("Realizando o download .... ", imagePath)
  urllib.request.urlretrieve(imagePath, fileName)  #realiza a requisição para a página da web


t0 = time.time() #armazena o tempo inicial de execução
for i in range(10):
    #imageName = "imagens/image-" + str(i) + ".jpg"  #coloca o nome em cada uma das imagens baixadas
    imageName = str(i)  #coloca o nome em cada uma das imagens baixadas
    downloadImagens("http://lorempixel.com/400/200/sports", imageName)  #aplica o download da imagem
  
t1 = time.time() #tempo final após a execução
totalTime = t1 - t0  #diferença de tempo entre o valor inical de execução e o final
print("Tempo toal de execução {}".format(totalTime))

# + colab={"base_uri": "https://localhost:8080/", "height": 374} colab_type="code" executionInfo={"elapsed": 2094, "status": "ok", "timestamp": 1597495930593, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="nZEnC-NFo1Nf" outputId="130f39c0-e51f-4194-ceae-814601ddc636"
#exedcução do download de imagens via multiplas threads
import threading
import urllib.request
import time

def downloadImagens(imagePath, fileName):
  print("Realizando o download .... ", imagePath)
  urllib.request.urlretrieve(imagePath, fileName)
  print("Download Finalizado")

def executeThread(i): 
  imageName = str(i)  #coloca o nome em cada uma das imagens baixadas
  downloadImagens("http://lorempixel.com/400/200/sports", imageName)


t0 = time.time()

threads = [] #lista vazia que vai conter todas as threads criadas

#cria das 10 threads, cada uma delas será responsável por realizar o download
for i in range(10):
  thread = threading.Thread(target=executeThread, args=(i,))
  threads.append(thread)
  thread.start()
  
#garante que as execuções foram finalizadas
for i in threads:
  i.join()

#calcula o tempo de execução
t1 = time.time()
totalTime = t1 - t0
print("Tempo total de execução {}".format(totalTime))

# + [markdown] colab_type="text" id="PviI5qNYOpZf"
# **Compartilhamento de tempo**

# + colab={} colab_type="code" id="R90lL9EROolp"
import threading  #módulo para a construção de multithreads
import time  #módulo para a medição de tempo
import random  #módulo para geração de números randomicos

counter = 10   #contador inicial

#função que adiciona um número para o contador
def tarefaA():
  global counter  #variável global 
  while counter < 30:
    counter += 1  #incrementa o contador
    print("A tarefaA incrementou o contador para {}".format(counter))
    sleepTime = random.randint(0,1) #escolhe, randomicamente, um valor entre 0 e 3
    time.sleep(sleepTime) #coloca a tread para dormir

#função que retira um número do contador
def tarefaB():
  global counter #variável global
  while counter > -30:
    counter -= 1  #decrementa o contador
    print("A tarefaB decrementou o contador para {}".format(counter))
    sleepTime = random.randint(0,3) #escolhe, randomicamente, um valor entre 0 e 3
    time.sleep(sleepTime) #coloca a tread para dormir


t0 = time.time()
thread1 = threading.Thread(target=tarefaA) #instancia um objeto da classe Thread para executar
                                           #a tarefaA
thread2 = threading.Thread(target=tarefaB) #instancia um objeto da classe Thread para executar
                                           #a tarefaB

thread1.start() #inicia a tread1
thread2.start() #inicia thread2

thread1.join()  #ceritifica o fim da execução
thread2.join() #certifica do fim da execução

t1 = time.time()

print("Tempo total de execução {}".format(t1-t0))

# + [markdown] colab_type="text" id="ZEv721D1A0L3"
# **Estados de execução de uma Thread**

# + colab={"base_uri": "https://localhost:8080/", "height": 119} colab_type="code" executionInfo={"elapsed": 10728, "status": "ok", "timestamp": 1597520482102, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="ls7X8ruRA3cl" outputId="189306fe-cc18-4b04-bdbd-2005cedfde9f"
import threading
import time

# função que, simplesmente, realiza o print de uma mensagem de execução e 
def threadWorker():
  # Neste ponto é onde ocorre a mudança do 'Runnable' para o 'Running'

  print("A thread entrou no estado 'Running'")

  # quando chamamos a função time.sleep() a 
  #thread entra para o estado de not-running
  print('A thread entrou no estado "Non-Running"')
  time.sleep(10)
  # quando a tarefa é finalizada, a thread é terminada 
  print("Execução da thread foi finalizada")
  #garbage collector



# neste momento a threada ainda "não possui estados"
#não existe alocação de recursos
print("Thread Criada")
myThread = threading.Thread(target=threadWorker)

#quando é chamado o método myThread.start(), python realiza a 
#alocação de recursos e, posteriormente, passa para o estado de
# "Start" para o "Runnable", mas sem entrar em execução.
print("Thread no estado 'Runnable'")
myThread.start()

#quando o metodo join é chamado, a thread passa para o estado
# "terminated"
myThread.join()
print("A thread está no estado de 'Terminated'")

# + [markdown] colab_type="text" id="bI5BpEbyEvhJ"
# **Outro exemplo de execução de uma Thread**

# + colab={"base_uri": "https://localhost:8080/", "height": 547} colab_type="code" executionInfo={"elapsed": 616, "status": "ok", "timestamp": 1597520582200, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="EMRp6YBvEznI" outputId="0fc252f9-dc7c-4767-db5c-085ed5b76ccd"
import threading
import time
import random

#função que recebe um número e cira uma thread
def executeThread(i):
  print("Thread {} incializada \n".format(i))
  sleepTime = random.randint(1,10)
  time.sleep(sleepTime)
  print("Thread {} finalizou a execução".format(i))

for i in range(10):
  thread = threading.Thread(target=executeThread, args=(i,))
  thread.start()

  print("Número de threads ativas:" , threading.enumerate())

# + [markdown] colab_type="text" id="YJigjQKFpGqr"
# **Herança com Threads**

# + colab={"base_uri": "https://localhost:8080/", "height": 119} colab_type="code" executionInfo={"elapsed": 552, "status": "ok", "timestamp": 1597525715306, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="H5zfWtzOpKFT" outputId="597fe291-193b-4515-a9f3-fb9bdd7594d1"
from threading import Thread

#define a classe como filha da classe Thread
class MinhaClasseThread(Thread):
  def __init__(self):
    print("Olá, construtor thread!!")
    Thread.__init__(self)

  #define a função run() que é chamada quando thread.start()
  def run(self):
    print("\nThread em execução.")

#instanciando um objeto da classe criada
minhaThread=MinhaClasseThread()
print("Objeto criado")
minhaThread.start()
print("Thread inicalizada")
minhaThread.join()
print("Thread finalizada")

# + [markdown] colab_type="text" id="Xai_uqZMvx-a"
# **Multiplas Threads**

# + colab={"base_uri": "https://localhost:8080/", "height": 374} colab_type="code" executionInfo={"elapsed": 534, "status": "ok", "timestamp": 1597526000492, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="RUgcgZDUv1AG" outputId="a559df1e-b407-43ef-8e3b-bfee0c16ec28"
import threading
 
class minhaThread (threading.Thread):
    def __init__(self, threadID, nome, contador):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.nome = nome
        self.contador = contador
    def run(self):
        print("Iniciando thread %s com %d processos" %(self.name,self.contador))
        processo(self.nome, self.contador)
        print("Finalizando " + self.nome)
 
def processo(nome, contador):
    while contador:
        print( "Thread %s fazendo o processo %d" % (nome, contador))
        contador -= 1
 
# Criando as threads
thread1 = minhaThread(1, "Alice", 8)
thread2 = minhaThread(2, "Bob", 8)
 
# Comecando novas Threads
thread1.start()
thread2.start()
 
threads = []
threads.append(thread1)
threads.append(thread2)
 
for t in threads:
    t.join()
 
print("Saindo da main")

# + [markdown] colab_type="text" id="sihVaGMQxYLE"
# **Contando Threads ativas**

# + colab={"base_uri": "https://localhost:8080/", "height": 1000} colab_type="code" executionInfo={"elapsed": 4597, "status": "ok", "timestamp": 1597526097273, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="CPFSAiFhxbo5" outputId="65cae8bc-8d7f-4a35-e713-803db5bcb747"
import threading
import time
import random


def minhaThread(i):
  print("Thread {}: inicializada".format(i))
  time.sleep(random.randint(1,5))
  print("\nThread {}: finalizada".format(i))

for i in range(random.randint(2,50)):
  thread=threading.Thread(target=minhaThread,args=(i,))
  thread.start()
time.sleep(4)
print("Total de Threads ativas: {}".format(threading.active_count()))

# + [markdown] colab_type="text" id="uTfSAOr0zGUG"
# **Em qual thread estamos?**

# + colab={"base_uri": "https://localhost:8080/", "height": 187} colab_type="code" executionInfo={"elapsed": 631, "status": "ok", "timestamp": 1597526158699, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="WJK3Sxw9zV75" outputId="71bb8462-8735-4ef0-d201-c22053a08240"
import threading
import time

def threadTarget():
  print("Thread atual: {}".format(threading.current_thread()))

threads = []

for i in range(10):
  thread = threading.Thread(target=threadTarget)
  thread.start()
  threads.append(thread)

for thread in threads:
  thread.join()

# + [markdown] colab_type="text" id="txQicA-J00jQ"
# **Main Thread**

# + colab={"base_uri": "https://localhost:8080/", "height": 153} colab_type="code" executionInfo={"elapsed": 5514, "status": "ok", "timestamp": 1597526195086, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="RB5cC-Fbz2cS" outputId="b9527f90-fb89-4a11-acce-be10afeb2a13"
import threading
import time

def myChildThread():
  print("Thread Filha inicializada ----")
  time.sleep(5)
  print("Thread Atual ----------")
  print(threading.current_thread())
  print("-------------------------")
  print("Main Thread -------------")
  print(threading.main_thread())
  print("-------------------------")
  print("Thread Filha Finalizada")


child = threading.Thread(target=myChildThread)
child.start()
child.join()

# + [markdown] colab_type="text" id="OYaGnqlc1jfR"
# **Identificando as Threads**

# + colab={"base_uri": "https://localhost:8080/", "height": 122} colab_type="code" executionInfo={"elapsed": 684, "status": "ok", "timestamp": 1597526235658, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="h9Re7tQ91mGd" outputId="1174c99e-409e-42cd-dbea-e3493054f58e"
import threading
import time


def myThread():
  print("Thread {} inicializada".format(threading.currentThread().getName()))
  time.sleep(10)
  print("Thread {} finalizada".format(threading.currentThread().getName()))

for i in range(4):
  threadName = "Thread-" + str(i)
  thread = threading.Thread(name=threadName, target=myThread)
  thread.start()

print("{}".format(threading.enumerate()))

# + [markdown] colab_type="text" id="4TubT6mI6Ypc"
# **Deadlock**

# + colab={"base_uri": "https://localhost:8080/", "height": 714} colab_type="code" executionInfo={"elapsed": 35482, "status": "error", "timestamp": 1597524147680, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="xlJV0qx36cLp" outputId="2aaa09dd-b11e-4c97-82fc-c69d3418a6ba"
import threading
import time
import random

class Filosofos(threading.Thread):

  def __init__(self, name, leftFork, rightFork):
    print("{} sentou na mesa".format(name))
    threading.Thread.__init__(self, name=name)
    self.leftFork = leftFork
    self.rightFork = rightFork

  def run(self):
    print("{} começou a pensar".format(threading.currentThread().getName()))
    while True:
      time.sleep(random.randint(1,5))
      print("{} parou de pensar".format(threading.currentThread().getName()))
      self.leftFork.acquire()
      time.sleep(random.randint(1,5))
      try:
        print("{} pegou o garfo da esquerda.".format(threading.currentThread().getName()))

        self.rightFork.acquire()
        try:
          print("{} pegou os dois garfos e começou a comer".format(threading.currentThread().getName()))
        finally:
          self.rightFork.release()   
          print("{} soltou o garfo da direita".format(threading.currentThread().getName()))
      finally:
        self.leftFork.release()
        print("{} soltou o garfo da esquerda".format(threading.currentThread().getName()))

fork1 = threading.RLock()
fork2 = threading.RLock()
fork3 = threading.RLock()
fork4 = threading.RLock()
fork5 = threading.RLock()

philosopher1 = Filosofos("Kant", fork1, fork2)
philosopher2 = Filosofos("Aristotle", fork2, fork3)
philosopher3 = Filosofos("Spinoza", fork3, fork4)
philosopher4 = Filosofos("Marx", fork4, fork5)
philosopher5 = Filosofos("Russell", fork5, fork1)

philosopher1.start()
philosopher2.start()
philosopher3.start()
philosopher4.start()
philosopher5.start()

philosopher1.join()
philosopher2.join()
philosopher3.join()
philosopher4.join()
philosopher5.join()

# + [markdown] colab_type="text" id="r0E9F6W48Iud"
# **Semáforos**

# + colab={"base_uri": "https://localhost:8080/", "height": 1000} colab_type="code" executionInfo={"elapsed": 25999, "status": "ok", "timestamp": 1597524683216, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="K8uG50RB-yrP" outputId="363ef48b-c83c-4821-dd52-a8e81b182bad"
import threading
import time
import random

class TicketSeller(threading.Thread):
  ticketsSold = 0

  def __init__(self, semaphore):
    threading.Thread.__init__(self);
    self.sem = semaphore
    print("Venda de ingressos inicializada")

  def run(self):
    global ticketsAvailable
    running = True
    while running:
      self.randomDelay()
      
      self.sem.acquire()
      if(ticketsAvailable <= 0):
        running = False
      else:
        self.ticketsSold = self.ticketsSold + 1
        ticketsAvailable = ticketsAvailable - 1
        print("{} acabou de vender 1 ({} restantes)".format(self.getName(), ticketsAvailable))
      self.sem.release()
    print("Venda de ingresso {} Ingressos vendidos no total {}".format(self.getName(), self.ticketsSold))

  def randomDelay(self):
    time.sleep(random.randint(0,4)/4)


# definição do nosso semáforo
semaphore = threading.Semaphore()
# Número de ingressos disponíveis
ticketsAvailable = 200

# os nossos vendedores
sellers = []
for i in range(4):
  seller = TicketSeller(semaphore)
  seller.start()
  sellers.append(seller)

# joining all our sellers
for seller in sellers:
  seller.join()


# + [markdown] colab_type="text" id="95fwmZEhOjUc"
# **Queue em Python**

# + colab={"base_uri": "https://localhost:8080/", "height": 1000} colab_type="code" executionInfo={"elapsed": 12721, "status": "ok", "timestamp": 1597527614849, "user": {"displayName": "<NAME>", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GiC2kqFihAn3Ile03oz-6rO8qVjEHv1DhGQ0ngQ5g=s64", "userId": "06907869093485551957"}, "user_tz": 180} id="heafwE_rOiq9" outputId="8f39742d-1e36-4ff2-a763-fc34558e7e6f"
#código adaptado de http://www.learn4master.com/algorithms/python-queue-for-multithreading
#  put(), get(), join() e task_done().
import threading
import time
from queue import Queue 

def consumidor(q):
    while(True):
        name = threading.currentThread().getName()
        print("Thread: {0} deseja obter um item da queue[tamanho atual = {1}] na data = {2} \n".format(name, q.qsize(), time.strftime('%H:%M:%S')))
        item = q.get();
        time.sleep(3)  # demora 3 segundos para adicionar um item
        print("Thread: {0} terminou de processar o item da queue[tamanho atual = {1}] na data = {2} \n".format(name, q.qsize(), time.strftime('%H:%M:%S')))
        q.task_done()


def produtor(q):
    # a thread principal vai adicionar itens para a queue

    for i in range(10):
        name = threading.currentThread().getName()
        print("Thread: {0} começou a adicionar um item na queue[tamanho atual = {1}] na data = {2} \n".format(name, q.qsize(), time.strftime('%H:%M:%S')))
        item = "item-" + str(i)
        q.put(item)
        print("Thread: {0} adicionou um item na queue[tamanho atual = {1}] na data = {2} \n".format(name, q.qsize(), time.strftime('%H:%M:%S')))

    q.join()

if __name__ == '__main__':
    q = Queue(maxsize = 3)

    threads_num = 3  # criação de 3 threads consumidoras
    for i in range(threads_num):
        t = threading.Thread(name = "ThreadConsumidora-"+str(i), target=consumidor, args=(q,))
        t.start()

    # criação de uma thread produtora
    t = threading.Thread(name = "ThreadProdutora", target=produtor, args=(q,))
    t.start()

    q.join()


# -



StarcoderdataJupyterScriptsDedupFiltered