Thursday 10 May 2012

Mutlithreading di Java, C# dan C++

Multi threading adalah sebuah cara pengeksekuisian beberapa program secara bersamaan. saling berbagi sumber daya tetapi dapat dijalankan secara independen.

Keuntungan dari Multi threading adalah :
  • Aplikasi interaktif menjadi tetap responsif meskipun sebagian dari program sedang diblok atau melakukan operasi lain yang panjang.
  • Berbagi sumber daya. Beberapa thread yang melakukan proses yang sama akan berbagi sumber daya. Keuntungannya adalah mengizinkan sebuah aplikasi untuk mempunyai beberapa thread yang berbeda dalam lokasi memori yang sama.
  • Ekonomis, Pembuatan sebuah proses memerlukan pengalokasian memori dan sumber daya. Alternatifnya adalah dengan menggunakan thread, karena thread membagi memori dan sumber daya yang dimilikinya sehingga lebih ekonomis untuk membuat thread dan context switching thread. Akan susah mengukur perbedaan waktu antara thread dan switch, tetapi secara umum pembuatan dan pengaturan proses akan memakan waktu lebih lama dibandingkan dengan thread. Pada Solaris, pembuatan proses memakan waktu 30 kali lebih lama dibandingkan pembuatan thread sedangkan proses context switch 5 kali lebih lama dibandingkan context switching thread.
  • Utilisasi arsitektur multiprosesor. Keuntungan dari multithreading dapat sangat meningkat pada arsitektur multiprosesor, dimana setiap thread dapat berjalan secara paralel di atas procesor yang berbeda. Pada arsitektur processor tunggal, CPU menjalankan setiap thread secara bergantian tetapi hal ini berlangsung sangat cepat sehingga menciptakan ilusi paralel, tetapi pada kenyataanya hanya satu thread yang dijalankan CPU pada satu-satuan waktu.




Csharp


using System;
using System.Threading;

namespace OOPpraktikum
{
 class Program
 {
  public static void Main(string[] args)
  {
   TesThread tes1 = new TesThread("Rizal Thread");
   TesThread tes2 = new TesThread("Cha Thread");
   
   Thread thd1 = new Thread(new ThreadStart(tes1.Thred));
   Thread thd2 = new Thread(new ThreadStart(tes2.Thred));
   
   thd1.Start();
   thd2.Start();
   
   Console.ReadKey(true);
  }
 }
 
 class TesThread
 {
  string nama;
  public TesThread(string nm)
  {
   nama = nm;
  }
  
  public void Thred()
  {
   for (byte i = 0; i<50; i++)
   {
    Console.WriteLine(nama+" "+(i+1));
    Thread.Sleep(1000);
   }
  }
 }
}  

Java


package OOPpraktikum;
import java.util.*;

public class MainClass
{
 static Scanner input = new Scanner(System.in);
 
 public static void main(String[] args) 
 {
  TesThread thd1 = new TesThread("Rizal Thread");
  TesThread thd2 = new TesThread("Cha Thread");
  
  thd1.start();
  thd2.start();
  
 }

}

class TesThread extends Thread
{
 String nama;
 public TesThread(String a)
 {
  nama = a;
 }
 public void run()
 {
  try
  {
   for(byte i = 0; i<50; i++)
   {
    Thread.sleep(1000);
    System.out.println(nama+" "+i);
   }
  }
  catch (Exception e) 
  {
   // TODO: handle exception
  }
  
 }
}
  


Khusus C++ untuk membuat Multi thread harus menggunakan header file, dalam contoh kode program berikut memanfaatkan header file buatan programmer lain. Referensinya ada pada http://www.codeproject.com/Articles/5218/Synchronized-multi-threading-in-C-No-MFC

C++

ou_thread.h

namespace openutils {
 class ThreadException;
 class Mutex;

 /** class Thread
   * Represents a thread of execution
   * in the process. To create a new Thread
   * write an inherited class ot Thread and
   * override the run() function
 **/
 class Thread {

 private:
  // unsigned long* to the low-level thread object
  unsigned long* m_hThread;
  // a name to identify the thread
  string m_strName;

 public:
  Thread();
  Thread(const char* nm);
  virtual ~Thread();
  void setName(const char* nm);
  string getName() const;
  void start();
  virtual void run();
  void sleep(long ms);
  void suspend();
  void resume();
  void stop();

  void setPriority(int p);

  bool wait(const char* m,long ms=5000);
  void release(const char* m);

 public:
  // Thread priorities
  static const int P_ABOVE_NORMAL;
  static const int P_BELOW_NORMAL;
  static const int P_HIGHEST;
  static const int P_IDLE;
  static const int P_LOWEST;
  static const int P_NORMAL;
  static const int P_CRITICAL;
 private:    
 };// class Thread 

 /** class Mutex
   * Represents a Mutex object to synchronize
   * access to shaed resources.
 **/
 class Mutex {
 private:
  // unsigned long* to the low-level mutex object
  unsigned long* m_hMutex;
  // name to identify the mutex
  string m_strName;
 public:
  Mutex();
  Mutex(const char* nm);
  void create(const char* nm);
  unsigned long* getMutexHandle();
  string getName();
  void release();
  ~Mutex();
 };

 /** class ThreadException
   * thrown by Thread and Mutex function 
   * calls
 **/
 class ThreadException {
 private:
  string msg;
 public:
  ThreadException(const char* m);
  string getMessage() const;
 }; 
} // namespace openutils

// global function called by the thread object.
// this in turn calls the overridden run()
extern "C" {
 unsigned int _ou_thread_proc(void* param);
}


    
  
ou_thread.cpp

#include <string>
using namespace std;

#include <windows.h>

#include "ou_thread.h"
using namespace openutils;

const int Thread::P_ABOVE_NORMAL = THREAD_PRIORITY_ABOVE_NORMAL;
const int Thread::P_BELOW_NORMAL = THREAD_PRIORITY_BELOW_NORMAL;
const int Thread::P_HIGHEST = THREAD_PRIORITY_HIGHEST;
const int Thread::P_IDLE = THREAD_PRIORITY_IDLE;
const int Thread::P_LOWEST = THREAD_PRIORITY_LOWEST;
const int Thread::P_NORMAL = THREAD_PRIORITY_NORMAL;
const int Thread::P_CRITICAL = THREAD_PRIORITY_TIME_CRITICAL;

/**@ The Thread class implementation
**@/

/** Thread()
  * default constructor
**/  
Thread::Thread() {
 m_hThread = NULL;
 m_strName = "null";
}

/** Thread(const char* nm)
  * overloaded constructor
  * creates a Thread object identified by "nm"
**/  
Thread::Thread(const char* nm) {
 m_hThread = NULL;
 m_strName = nm;
}

Thread::~Thread() {
 if(m_hThread != NULL) {
  stop();
 }
}

/** setName(const char* nm)
  * sets the Thread object's name to "nm"
**/  
void Thread::setName(const char* nm) { 
 m_strName = nm;
}

/** getName()
  * return the Thread object's name as a string
**/  
string Thread::getName() const { 
 return m_strName;
}

/** run()
  * called by the thread callback _ou_thread_proc()
  * to be overridden by child classes of Thread
**/ 
void Thread::run() {
 // Base run
}

/** sleep(long ms)
  * holds back the thread's execution for
  * "ms" milliseconds
**/ 
void Thread::sleep(long ms) {
 Sleep(ms);
}

/** start()
  * creates a low-level thread object and calls the
  * run() function
**/ 
void Thread::start() {
 DWORD tid = 0; 
 m_hThread = (unsigned long*)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_ou_thread_proc,(Thread*)this,0,&tid);
 if(m_hThread == NULL) {
  throw ThreadException("Failed to create thread");
 }else {
  setPriority(Thread::P_NORMAL);
 }
}

/** stop()
  * stops the running thread and frees the thread handle
**/ 
void Thread::stop() {
 if(m_hThread == NULL) return; 
 WaitForSingleObject(m_hThread,INFINITE);
 CloseHandle(m_hThread);
 m_hThread = NULL;
}

/** setPriority(int tp)
  * sets the priority of the thread to "tp"
  * "tp" must be a valid priority defined in the
  * Thread class
**/ 
void Thread::setPriority(int tp) {
 if(m_hThread == NULL) {
  throw ThreadException("Thread object is null");
 }else {
  if(SetThreadPriority(m_hThread,tp) == 0) {
   throw ThreadException("Failed to set priority");
  }
 }
}

/** suspend()  
  * suspends the thread
**/ 
void Thread::suspend() {
 if(m_hThread == NULL) {
  throw ThreadException("Thread object is null");
 }else {
  if(SuspendThread(m_hThread) < 0) {
   throw ThreadException("Failed to suspend thread");
  }
 }
}

/** resume()  
  * resumes a suspended thread
**/ 
void Thread::resume() {
 if(m_hThread == NULL) {
  throw ThreadException("Thread object is null");
 }else {
  if(ResumeThread(m_hThread) < 0) {
   throw ThreadException("Failed to resume thread");
  }
 }
}

/** wait(const char* m,long ms)  
  * makes the thread suspend execution until the
  * mutex represented by "m" is released by another thread.
  * "ms" specifies a time-out for the wait operation.
  * "ms" defaults to 5000 milli-seconds
**/ 
bool Thread::wait(const char* m,long ms) {
 HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
 if(h == NULL) {
  throw ThreadException("Mutex not found");
 }
 DWORD d = WaitForSingleObject(h,ms);
 switch(d) {
 case WAIT_ABANDONED:
  throw ThreadException("Mutex not signaled");
  break;
 case WAIT_OBJECT_0:
  return true;
 case WAIT_TIMEOUT:
  throw ThreadException("Wait timed out");
  break;
 }
 return false;
}

/** release(const char* m)  
  * releases the mutex "m" and makes it 
  * available for other threads
**/ 
void Thread::release(const char* m) {
 HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
 if(h == NULL) {
  throw ThreadException("Invalid mutex handle");
 }
 if(ReleaseMutex(h) == 0) {
  throw ThreadException("Failed to release mutex");
 }
}

/**@ The Mutex class implementation
**@/

/** Mutex()
  * default constructor
**/  
Mutex::Mutex() {
 m_hMutex = NULL;
 m_strName = "";
}

/** Mutex(const char* nm)
  * overloaded constructor
  * creates a Mutex object identified by "nm"
**/  
Mutex::Mutex(const char* nm) { 
 m_strName = nm; 
 m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
 if(m_hMutex == NULL) {
  throw ThreadException("Failed to create mutex");
 }
}

/** create(const char* nm)
  * frees the current mutex handle.
  * creates a Mutex object identified by "nm"
**/  
void Mutex::create(const char* nm) {
 if(m_hMutex != NULL) {
  CloseHandle(m_hMutex);
  m_hMutex = NULL;
 }
 m_strName = nm;
 m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
 if(m_hMutex == NULL) {
  throw ThreadException("Failed to create mutex");
 }
}
/** getMutexHandle()
  * returns the handle of the low-level mutex object
**/  
unsigned long* Mutex::getMutexHandle() {
 return m_hMutex;
}

/** getName()
  * returns the name of the mutex
**/ 
string Mutex::getName() {
 return m_strName;
}

void Mutex::release() {
 if(m_hMutex != NULL) {
  CloseHandle(m_hMutex);
 }
}

Mutex::~Mutex() {
 /*if(m_hMutex != NULL) {
  CloseHandle(m_hMutex);
 }*/
}

// ThreadException
ThreadException::ThreadException(const char* m) {
 msg = m;
}

string ThreadException::getMessage() const {
 return msg;
}

// global thread caallback
unsigned int _ou_thread_proc(void* param) {
 Thread* tp = (Thread*)param;
 tp->run();
 return 0;
}  

Main Program
#include <cstdlib>
#include <iostream>
#include <STRING>

using namespace std;
#include "ou_thread.h"
using namespace openutils;

class MyThread : public Thread {
private:
    int m_nCount;
public:
    MyThread(int n,const char* nm) {
        Thread::setName(nm);
        m_nCount = n;
    }
    void run() {
        for(int i=0;i<m_nCount;i++) {
            cout << getName().c_str()<<" "<<i<< endl;
            sleep(1000);
        }
    }
};

int main(int argc, char *argv[])
{
    Thread *t1 = new MyThread(50,"Rizal Thread");
    Thread *t2 = new MyThread(50,"Cha Thread");
    try 
    {
        t1->start();
        t2->start();
        t1->stop();
        t2->stop();
    }
    catch(ThreadException ex) 
    {
        printf("%s\n",ex.getMessage().c_str());
    } 
    delete t1;
    delete t2;
      
    system("PAUSE");
    return EXIT_SUCCESS;
}

  

1 comment:

  1. This is very interesting, You're a very skilled blogger. I've joined your feed and look forward to seeking more of
    your fantastic post. Also, I've shared your website in my social networks!

    My homepage: best cellulite treatment

    ReplyDelete