View Full Version : سوال: نحوه استفاده از Thread در جاوا
سعیدسعید
سه شنبه 21 اردیبهشت 1389, 00:05 صبح
با سلام خدمت همه دوستان خوبم
چه جوری میشه از Thread استفاده کرد؟ کاری که من کردم به صورت زیره.
تعریف زیر برای کلاس Base است:
[
Public Class MyBase extends Thread implements Runnable
{
.....
public void run()
{
}
}
در کلاس فوق داخل متد run خالیه و توش کدی نوشته نشده.
یعنی می خوام متد run رو در داخل کلاس های فرزند این کلاس Base پر کنم.
public class MyChild extends MyBase
{
...
public void run()
{
//some statements I have Here
}
}
ایا کاری که من انجام میدهم درسته؟ اجرا که میکنم هیچ اتفاقی نمیفته. انگار متدهای run کلاس های فرزند اجرا نمی شوند.
ایا راه حلی دارید؟
ممنون از راهنمایی و لطفتون
ebrahhimi
شنبه 25 اردیبهشت 1389, 10:54 صبح
آیا اصلا thread رو ایجاد می کنی؟؟؟
تو Constructor باید یه ترد ایجاد کنی
Thread t;
MyBase(){
t = new Thread(this,"Demo Thread");
System.out.println("Child thread :" + t);
t.start
{
manvaputra
شنبه 25 اردیبهشت 1389, 11:08 صبح
دوست عزیز آموزش کامل ترد در جاوا در توی همین فروم هست به آدرس زیر مراجعه نمایید:
Thread در جاوا (قسمت اول) (http://barnamenevis.org/forum/showthread.php?t=123116)
Thread در جاوا (قسمت دوم:ایجاد ترد با استفاده از روش بسط کلاس Thread) (http://barnamenevis.org/forum/showthread.php?t=123261)
Thread در جاوا (قسمت سوم:ایجاد ترد با استفاده از واسط Runnable) (http://barnamenevis.org/forum/showthread.php?p=599192#post599192)
Thread در جاوا (قسمت چهارم:پیاده سازی مثال چت با استفاده از مالتی ترد) (http://barnamenevis.org/forum/showthread.php?p=604205#post604205)
javanerd
یک شنبه 26 اردیبهشت 1389, 17:02 عصر
آیا اصلا thread رو ایجاد می کنی؟؟؟
تو Constructor باید یه ترد ایجاد کنی
Thread t;
MyBase(){
t = new Thread(this,"Demo Thread");
System.out.println("Child thread :" + t);
t.start
{
واقعیت اینه که ایجاد کردن یک thread در سازندهی یک کلاس و فراخوانی کردن تابع start اون زیاد کار جالبی نیست. در مثالی که شما نوشتید و در بسیاری از مثال های دیگه ممکنه که این کار هیچ مشکلی به وجود نیاره، ولی بعضی وقتها این کار باعث به وجود آمدن یک باگ در برنامه میشه که پیدا کردنش خیلی خیلی سخته.
اگر threadی که توی سازنده فراخوانی شده از فیلدهای کلاس استفاده کنه ممکنه قبل از اینکه سازنده فرصت پیدا کنه که به این فیلدها مقدار بده، اجرای thread به نقطهای برسه که از این فیلدها استفاده می کنه. در این صورت برنامه با مشکل مواجه میشه.
اگر کسی از این کلاس MyBase یک زیر کلاس بسازه احتمال اینکه این مشکل به وجود بیاد بیشتر میشه، چون وقتی که اجرای thread شروع میشه هنوز سازندهی کلاس فرزند اجرا نشده و فیلدهای کلاس فرزند مقدار دهی نشده هستند.
mohsensaghafi
یک شنبه 26 اردیبهشت 1389, 19:54 عصر
سلام دوستان.
واقعیت اینه که ایجاد کردن یک thread در سازندهی یک کلاس و فراخوانی کردن تابع start اون زیاد کار جالبی نیست. در مثالی که شما نوشتید و در بسیاری از مثال های دیگه ممکنه که این کار هیچ مشکلی به وجود نیاره، ولی بعضی وقتها این کار باعث به وجود آمدن یک باگ در برنامه میشه که پیدا کردنش خیلی خیلی سخته.
اگر threadی که توی سازنده فراخوانی شده از فیلدهای کلاس استفاده کنه ممکنه قبل از اینکه سازنده فرصت پیدا کنه که به این فیلدها مقدار بده، اجرای thread به نقطهای برسه که از این فیلدها استفاده می کنه. در این صورت برنامه با مشکل مواجه میشه.
ببین دوست عزیز، ببینید منظور شما سازنده کدوم کلاسه؟! تو سازنده همون کلاس که خودش رو کسی run نمی کنه. اگر منظور هم داخل کلاس های دیگه باشه، چون اول می سازیمش، تمام متغییر ها مقدار گرفتن، ولی اگر منظورتون اینه که توی سازنده یه کلاس یه ترد رو تعریف کنید و اون رو run کنید و اون ترد از مقادیر کلاس اول استفاده کند، حرف شما درست است و راه کارش اینه که اواخر سازنده ترد رو run کنید.
اگر کسی از این کلاس MyBase یک زیر کلاس بسازه احتمال اینکه این مشکل به وجود بیاد بیشتر میشه، چون وقتی که اجرای thread شروع میشه هنوز سازندهی کلاس فرزند اجرا نشده و فیلدهای کلاس فرزند مقدار دهی نشده هستند.
این قسمت هم همونه. این جا هم بستگی داره کجا دستور start رو اجرا کنید.
mohsensaghafi
یک شنبه 26 اردیبهشت 1389, 20:10 عصر
دوست عزیز.
این هم یه نمونه ساده از یه کلاس که هست که هم خودش هم فرزندش هر دو ترد هستند.
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new myChild().start();
new myBase().start();
}
}
class myBase extends Thread implements Runnable{
int counter;
public myBase(){
counter=10;
}
@Override
public void run(){
for(int i=counter;i>=0;i--)
System.out.println(i);
}
}
class myChild extends myBase{
public myChild(){
super();
}
@Override
public void run(){
for(int i=0;i<=counter;i++)
System.out.println(i);
}
}
اگر هم بخوای که فقط کلاس فرزند run داشته باشه، برای کلاس والد هیچ تعریفی از run نمی خواد بگذاری.
mahdi68
دوشنبه 27 اردیبهشت 1389, 22:05 عصر
چه طور میشه متد Thread.start() دوبار اجرا کرد مثلا وقتی یه بار اجرا میشه هر ثانیه به یک متغییر یک واحد اضافه کنه و وقتی دوباره اجرا میشه هر ثانیه به یک متغییر یک واحد کم کنه ؟؟؟
mahdi68
دوشنبه 27 اردیبهشت 1389, 23:12 عصر
چه جوری میشه یک thread متوفق کرد تا دوباره بشه start کرد ؟؟؟
mohsensaghafi
دوشنبه 27 اردیبهشت 1389, 23:37 عصر
سلام دوست عزیز.
یک ترد باید کامل اجرا بشه و تموم بشه. برای اینکه بخواید چند بار ترد رو run کنید باید چند ترد مختلف رو جداگانه run کنید. یه متغیر که می گید می خواد اضافه یا کم بشه رو بصورت پارامتر به برنامه بفرستید. و هر بار یه ترد جدید تعریف کنید و اون رو ران کنید.
mahdi68
دوشنبه 27 اردیبهشت 1389, 23:53 عصر
ببین دوست عزیز دو تا thread به نام های t1 و t2 تعریف میکنم بعد
public void run(){
if(true)
.........
if(fulse)
.......
که وقتی t1 شروع میکنم true و وقتی t2 بشمسث اجرا بشه
حالا t1 اجرا میشه ولی t2 نه !!!
mahdi68
دوشنبه 27 اردیبهشت 1389, 23:59 عصر
این میده
java.lang.NullPointerException
at org.netbeans.mobility.antext.StackTraceTranslator. getLineNumber(StackTraceTranslator.java:216)
at org.netbeans.mobility.antext.StackTraceTranslator. translate(StackTraceTranslator.java:118)
at org.netbeans.mobility.antext.RunTask$StackTraceTra nslatorHandler$1.flush(RunTask.java:771)
at org.netbeans.mobility.antext.RunTask$StackTraceTra nslatorHandler$1.run(RunTask.java:817)
at java.lang.Thread.run(Thread.java:619)
mohsensaghafi
سه شنبه 28 اردیبهشت 1389, 00:30 صبح
سلام دوست عزیز.
باید با suspend و resume می تونید کنترلشون کنید.
mahdi68
سه شنبه 28 اردیبهشت 1389, 00:50 صبح
سلام دوست عزیز.
باید با suspend و resume می تونید کنترلشون کنید.
میشه یکم بیشتر توضیح بدین ؟؟؟
mohsensaghafi
سه شنبه 28 اردیبهشت 1389, 11:04 صبح
mahdi68
نقل قول: نحوه استفاده از Thread در جاوا
نقل قول:
نوشته شده توسط mohsensaghafi
سلام دوست عزیز.
باید با suspend و resume می تونید کنترلشون کنید.
میشه یکم بیشتر توضیح بدین ؟؟؟
سلام دوست عزیز.
من یه برنامه واستون نوشتم که دو تا ترد، همدیگه رو کنترل می کنن.
فکر می کنم با دیدن کد مشکلتون حل بشه.
باز هم اگر جاییش گنگ بود، بگید تا بیشتر توضیح بدم.
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
myBase t1 = new myBase(10);
myBase t2 = new myBase(9);
t1.seto(t2);
t2.seto(t1);
t1.start();
t2.start();
}
}
class myBase extends Thread implements Runnable{
int counter;
myBase other;
public myBase(int inti){ // initialize the counter atribiute.
counter=inti;
}
public void seto(myBase o){ // for set the address of other thread for control.
other=o;
}
@Override
public void run(){
for(;counter>=0;counter--){ // count and print from 10 to 0
System.out.print(this.getName()+"-> ");
System.out.println(counter);
if(counter%5==0){ // after print each 5 numbers, switch to another thread.
other.resume();
if(counter!=0) // if the counter is 0, do not suspend itself. if don't pot this
// "if" the program going to deadluck.
this.suspend();
}
}
}
}
mahdi68
سه شنبه 28 اردیبهشت 1389, 11:55 صبح
دوست عزیز من کدی که خددم نوشتم اینجا میزارم اگه زحمتی نیست یه نگاهی بکنین بگین مشکلش چیه متشکرم
public class NewJFrame extends javax.swing.JFrame implements Runnable {
Thread t1, t2;
int x = 0;
boolean y = false;
public NewJFrame() {
initComponents();
t1 = new Thread(this);
t2 = new Thread(this);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
t1.start();
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
t2.start();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
public void run() {
if (y == false) {
while (x < 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Le vel.SEVERE, null, ex);
}
x++;
jTextField1.setText(String.valueOf(x));
y = true;
}
} else {
if (y == true) {
while (x > 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Le vel.SEVERE, null, ex);
}
x--;
jTextField1.setText(String.valueOf(x));
y = false;
}
}
}
}
}
javanerd
سه شنبه 28 اردیبهشت 1389, 13:42 عصر
ولی اگر منظورتون اینه که توی سازنده یه کلاس یه ترد رو تعریف کنید و اون رو run کنید و اون ترد از مقادیر کلاس اول استفاده کند، حرف شما درست است و راه کارش اینه که اواخر سازنده ترد رو run کنید.
دقیقا منظورم همین بود. خیلی ممنون به خاطر شفاف سازی
javanerd
سه شنبه 28 اردیبهشت 1389, 13:56 عصر
سلام دوست عزیز.
باید با suspend و resume می تونید کنترلشون کنید.
استفاده از متدهای suspend و resume به خاطر اینکه ممکنه باعث بهوجود آمدن deadlock بشه در حال منسوخ شدن هست. این تابعها توی نسخهی فعلی جاوا (نسخهی ۱٫۶) deprecate شدند. بعید نیست توی نسخههای بعدی حذف بشن.
javanerd
سه شنبه 28 اردیبهشت 1389, 14:11 عصر
سلام دوستان.
ببین دوست عزیز، ببینید منظور شما سازنده کدوم کلاسه؟! تو سازنده همون کلاس که خودش رو کسی run نمی کنه. اگر منظور هم داخل کلاس های دیگه باشه، چون اول می سازیمش، تمام متغییر ها مقدار گرفتن، ولی اگر منظورتون اینه که توی سازنده یه کلاس یه ترد رو تعریف کنید و اون رو run کنید و اون ترد از مقادیر کلاس اول استفاده کند، حرف شما درست است و راه کارش اینه که اواخر سازنده ترد رو run کنید.
این قسمت هم همونه. این جا هم بستگی داره کجا دستور start رو اجرا کنید.
این یک مثال از کدی که پیدا کردن اشکالش کار حضرت فیله. البته شاید از هر هزار دفعه اجرا فقط یکبار ترد زودتر از سازندهی کلاس فرزند اجرا بشه.
public class ThreadDemo {
public static void main(final String[] args) {
new ChildClass();
}
}
class MyThread extends Thread {
private final BaseClass workingClass;
public MyThread(final BaseClass aBaseClass) {
this.workingClass = aBaseClass;
}
@Override
public void run() {
System.out.println("This thread is workin on "
+ this.workingClass.getDescription());
}
}
class BaseClass {
public BaseClass() {
final MyThread myThread = new MyThread(this);
myThread.start();
}
protected String getDescription() {
return "This is the base class";
}
}
class ChildClass extends BaseClass {
private final String description;
public ChildClass() {
this.description = "This is the ";
}
@Override
protected String getDescription() {
return this.description;
}
}
mohsensaghafi
چهارشنبه 29 اردیبهشت 1389, 15:55 عصر
استفاده از متدهای suspend و resume به خاطر اینکه ممکنه باعث بهوجود آمدن deadlock بشه در حال منسوخ شدن هست. این تابعها توی نسخهی فعلی جاوا (نسخهی ۱٫۶) deprecate شدند. بعید نیست توی نسخههای بعدی حذف بشن.
کنترل اینکه برنامه به حالت deadluck نره کار شما به عنوان برنامه نویسه. تمام دستوراتی که دست برنامه نویس رو باز می ذاره، یه نکته منفی هم داره، اما شما باید از اونا درست استفاده کنید که دچار مشکل نشید. نمونش اشاره گر ها هستن که بسیار دست برنامه نویس رو باز می ذارن که باز هم متاسفانه جاوا اونا رو ignore کرده.
mohsensaghafi
چهارشنبه 29 اردیبهشت 1389, 18:48 عصر
این یک مثال از کدی که پیدا کردن اشکالش کار حضرت فیله. البته شاید از هر هزار دفعه اجرا فقط یکبار ترد زودتر از سازندهی کلاس فرزند اجرا بشه.
public class ThreadDemo {
public static void main(final String[] args) {
new ChildClass();
}
}
class MyThread extends Thread {
private final BaseClass workingClass;
public MyThread(final BaseClass aBaseClass) {
this.workingClass = aBaseClass;
}
@Override
public void run() {
System.out.println("This thread is workin on "
+ this.workingClass.getDescription());
}
}
class BaseClass {
public BaseClass() {
final MyThread myThread = new MyThread(this);
myThread.start();
}
protected String getDescription() {
return "This is the base class";
}
}
class ChildClass extends BaseClass {
private final String description;
public ChildClass() {
this.description = "This is the ";
}
@Override
protected String getDescription() {
return this.description;
}
}
دوست عزیز
اولاً برنامه ای با این همه پیچیدگی کلاس ها، به نظر شما مشکلی در طراحی کلاس هایش ندارد؟ وقتی چند کلاس به این شکل به هم وابسته می شوند، جایی در طراحی کلاس ها دچار مشکل هستید.
دوماً باز هم این وظیفه شما به عنوان برنامه نویس است که کنترل روند اجرای برنامه را درست ایجاد کنید؟!
سوماً در این برنامه مشکل که واضح است. چون سازنده کلاس والد قبل از سازنده کلاس فرزند اجرا می شود، پس قطعاً دستور Start قبل از سازنده کلاس فرزند اجرا می شود اما اینکه چرا در بعضی مواقع درست کار می کند دلیلش مربوط می شود به برهه زمانی و تعویض ترد ها در CPU . و تنها دلیل این موضوع همین است و اجرای ترد (دستور start) همواره قبل از اجرای دستورات تابع سازنده کلاس فرزند اجرا می شود، نه هر هزار دفعه یک دفعه!
mohsensaghafi
چهارشنبه 29 اردیبهشت 1389, 19:31 عصر
دوست عزیز من کدی که خددم نوشتم اینجا میزارم اگه زحمتی نیست یه نگاهی بکنین بگین مشکلش چیه متشکرم
public class NewJFrame extends javax.swing.JFrame implements Runnable {
Thread t1, t2;
int x = 0;
boolean y = false;
public NewJFrame() {
initComponents();
t1 = new Thread(this);
t2 = new Thread(this);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
t1.start();
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
t2.start();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
public void run() {
if (y == false) {
while (x < 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Le vel.SEVERE, null, ex);
}
x++;
jTextField1.setText(String.valueOf(x));
y = true;
}
} else {
if (y == true) {
while (x > 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Le vel.SEVERE, null, ex);
}
x--;
jTextField1.setText(String.valueOf(x));
y = false;
}
}
}
}
}
سلام دوست عزیز.
من متوجه نشدم مشکلتون با این برنامه کجاست. این برنامه کامپایل می شه و اجرا می شه. پس مادامی که نگفتید که می خواید این برنامه براتون چکار بکنه، داره درست کار می کنه.
لطفا بگید که صورت برنامه ای که برای خودتون تعریف کردید چی بوده تا بگم که مشکلتون کجاست!
mahdi68
چهارشنبه 29 اردیبهشت 1389, 22:11 عصر
چون تو پست های قبلی گفته بودم دیگه نگفتم
بله کامپایل و اجرا میشه وقتی کلید 1 زده میشه از یک تا 10 تو تکست باکس نشون میده حالا میخوام بعد از اون وقتی کلید 2 زده میشه از 10 تا 1 بر عکس چاپ کنه که نمیشه !!!
javanerd
پنج شنبه 30 اردیبهشت 1389, 10:45 صبح
اجرای ترد (دستور start) همواره قبل از اجرای دستورات تابع سازنده کلاس فرزند اجرا می شود، نه هر هزار دفعه یک دفعه!
ببخشید، من اشتباه نوشته بودم. ممنون که یادآوری کردید. اینجا اصلاح می کنم:
«البته شاید از هر هزار دفعه اجرا فقط یکبار ترد زودتر از سازندهی کلاس فرزند اجرا نشه.»
در ضمن برای اینکه دوباره سو تفاهم پیش نیاد مظورم از اجرا شدن ترد اینه که کدی که توی تابع run نوشته شده شروع به اجرا کنه (ممکنه بلافاصله بعد از فراخوانی شدن تابع start تابع run شروع به کار نکنه)
mohsensaghafi
پنج شنبه 30 اردیبهشت 1389, 20:08 عصر
چون تو پست های قبلی گفته بودم دیگه نگفتم
بله کامپایل و اجرا میشه وقتی کلید 1 زده میشه از یک تا 10 تو تکست باکس نشون میده حالا میخوام بعد از اون وقتی کلید 2 زده میشه از 10 تا 1 بر عکس چاپ کنه که نمیشه !!!
واسه این کار مشکل تو شرط حلقه while هستش. شما بار اول که شمارش رو آغاز کردید مقدار x به 10 تغییر کرده و 10 از 10 کوچکتر نیست. شما باید شرط حلقه while دوم رو به x>0 تغییر بدی.
mohsensaghafi
پنج شنبه 30 اردیبهشت 1389, 20:12 عصر
ببخشید، من اشتباه نوشته بودم. ممنون که یادآوری کردید. اینجا اصلاح می کنم:
«البته شاید از هر هزار دفعه اجرا فقط یکبار ترد زودتر از سازندهی کلاس فرزند اجرا نشه.»
در ضمن برای اینکه دوباره سو تفاهم پیش نیاد مظورم از اجرا شدن ترد اینه که کدی که توی تابع run نوشته شده شروع به اجرا کنه (ممکنه بلافاصله بعد از فراخوانی شدن تابع start تابع run شروع به کار نکنه)
برای حل این مشکل، شاید بشه با یه دستور sleep کم، این همزمانی رو بوجود آورد هر چند که کماکان به نظر می رسه این همه پیچیدگی کلاس ها در طراحی مشکل داشته باشه.
موفق و پیروز
mahdi68
پنج شنبه 30 اردیبهشت 1389, 23:25 عصر
واسه این کار مشکل تو شرط حلقه while هستش. شما بار اول که شمارش رو آغاز کردید مقدار x به 10 تغییر کرده و 10 از 10 کوچکتر نیست. شما باید شرط حلقه while دوم رو به x>0 تغییر بدی.
بله دوست عزیز حق با شماست درست شد , حالا یه مشکل دیگه دارم وقتی اجرای هر دو ترد تموم میشه یعنی وقتی شمارش از یک تا 10 و بعد برعکس انجام میشه وقتی دوباره کلید 1 میزنم خطا میده یعنی وقتی برای بار دوم بعد از اجرا شدن t.start() فراخوانی میشه !!! مشکل از چی هست ؟؟؟
متشکرم
mohsensaghafi
جمعه 31 اردیبهشت 1389, 11:01 صبح
وقتی برای بار دوم بعد از اجرا شدن t.start() فراخوانی میشه !!! مشکل از چی هست ؟؟؟
دوست عزیز سلام.
شما یه instance از یک کلاس ترد رو بیشتر از 1 بار نمی تونید strat کنید. برای حل این مشکل بجای اینکه در قسمت سازنده کلاستون، ترد ها رو بسازید، در قسمت کلیک این کار رو انجام بدید و همونجا هم start کنید. این طوری هر بار یه instanceجدید درست می شه و هر بار می شه دوباره runش کرد.
موفق و پیروز
یا علی!
mahdi68
جمعه 31 اردیبهشت 1389, 13:43 عصر
دوست عزیز متشکر این مشکت هم حل شد
یک سوال دیگه چه طوری میتونم اجرای یک thread متوقف کنم ؟؟؟ من وقتی از join استفاده میکنم منتظر میمونه تا اون یکی تموم بشه
mohsensaghafi
شنبه 01 خرداد 1389, 08:52 صبح
دوست عزیز متشکر این مشکت هم حل شد
یک سوال دیگه چه طوری میتونم اجرای یک thread متوقف کنم ؟؟؟ من وقتی از join استفاده میکنم منتظر میمونه تا اون یکی تموم بشه
سلام دوست عزیز.
می تونی از تابع Stop استفاده کنی. اما یادت باشه مواظب باش که deadluck نشه.
یا علی!
mahdi68
شنبه 01 خرداد 1389, 11:11 صبح
می تونی از تابع Stop استفاده کنی. اما یادت باشه مواظب باش که deadluck نشه.
آخه همچین متدی نتونستم پیدا کنم !!! من هم تو یه کتاب نگاه کردم و هم وقتی تو کد میزنم همچین چیزی نمیاره !!! امکان داره یکم بیشتر توضیح بدین ؟؟؟
متشکرم
javanerd
شنبه 01 خرداد 1389, 16:46 عصر
دوست عزیز
اولاً برنامه ای با این همه پیچیدگی کلاس ها، به نظر شما مشکلی در طراحی کلاس هایش ندارد؟ وقتی چند کلاس به این شکل به هم وابسته می شوند، جایی در طراحی کلاس ها دچار مشکل هستید.
وقتی که داشتم این کد رو مینوشتم فقط به این موضوع فکر میکردم که یه جوری کد رو بنویسم که این اشکال توش ظاهر بشه. به فکر درست طراحی کردن کلاسها نبودم. اما الان هم به این تکه کد نگاه میکنم میبینم که طراحی پیچیدهای نداره. یک کلاس جد، یک کلاس فرزند یک ترد و یک کلاس که ترد رو فراخوانی میکنه.
نکتهای که شما بهش اشاره کردید نشون میده که حتی برای یک تکه کد خیلی ساده مثل کدی که من نوشتم هم پیدا کردن یک اشکال اینچنینی کار سختی هست، چه برسه به برنامههای بزرگ.
در ضمن اگر ممکنه راهنمایی کنید که چطور میشه این کلاسها رو بهتر طراحی کرد. من چیزی به ذهنم نمیرسه.
mohsensaghafi
یک شنبه 02 خرداد 1389, 09:04 صبح
وقتی که داشتم این کد رو مینوشتم فقط به این موضوع فکر میکردم که یه جوری کد رو بنویسم که این اشکال توش ظاهر بشه. به فکر درست طراحی کردن کلاسها نبودم. اما الان هم به این تکه کد نگاه میکنم میبینم که طراحی پیچیدهای نداره. یک کلاس جد، یک کلاس فرزند یک ترد و یک کلاس که ترد رو فراخوانی میکنه.
نکتهای که شما بهش اشاره کردید نشون میده که حتی برای یک تکه کد خیلی ساده مثل کدی که من نوشتم هم پیدا کردن یک اشکال اینچنینی کار سختی هست، چه برسه به برنامههای بزرگ.
در ضمن اگر ممکنه راهنمایی کنید که چطور میشه این کلاسها رو بهتر طراحی کرد. من چیزی به ذهنم نمیرسه.
سلام دوست عزیز.
من که مشکل کار رو بهت گفتم کجاست. حتی دلیل ایجاد شدنش و یکی از راه های نه خیلی کارامدش رو هم گفتم. اما اینکه می گم کلاس ها مشکل طراحی دارن منظورم اینه که در دنیای واقعی برنامه نویسی اگر به قواعد OOT توجه کنید هرگز کلاس هایی با این پیچیدگی نیاز نخواهید داشت. و اینکه طراحی درست یه مسئله چی هست بستگی به صورت پروژه داره. کلاسها بازنمایی از پدیده های دنیای واقعی هستند. نمی توان یک سری کلاس هایی که برای تست یک موضوع نوشته شده اند را تحلیل و بررسی کرد.
یا علی!
javanerd
یک شنبه 02 خرداد 1389, 10:31 صبح
اجازه بدهید که من سناریویی که ممکن هست منجر به وجود آمدن این مشکل بشه رو توضیح بدهم. (سر خودم اومده)
شما یک کلاس دارید که یک label رو پیادهسازی میکنه (کلاس پدر). این label با استفاده از یک thread توی زمانهای خاصی رنگش عوض میشه (یا یه کار دیگه انجام میده). میخواهید یک زیر کلاس از این کلاس بسازید تا یکی از کارهایی که این label انجام میده رو تغییر بدهید (کلاس فرزند). از این label جدید هم قرار هست توی یک فرم استفاده کنید. به نظر شما باید چیکار کرد؟ کلاسی که فرم رو پیادهسازی میکنه و کلاسی که label اصلی رو پیادهسازی میکنه ضروری هستند و شما نمیتونید بهشون دست بزنید. برای اینکه این label رو specialize کنید چه راهی پیشنهاد میدهید؟
mohsensaghafi
دوشنبه 03 خرداد 1389, 10:41 صبح
اجازه بدهید که من سناریویی که ممکن هست منجر به وجود آمدن این مشکل بشه رو توضیح بدهم. (سر خودم اومده)
شما یک کلاس دارید که یک label رو پیادهسازی میکنه (کلاس پدر). این label با استفاده از یک thread توی زمانهای خاصی رنگش عوض میشه (یا یه کار دیگه انجام میده). میخواهید یک زیر کلاس از این کلاس بسازید تا یکی از کارهایی که این label انجام میده رو تغییر بدهید (کلاس فرزند). از این label جدید هم قرار هست توی یک فرم استفاده کنید. به نظر شما باید چیکار کرد؟ کلاسی که فرم رو پیادهسازی میکنه و کلاسی که label اصلی رو پیادهسازی میکنه ضروری هستند و شما نمیتونید بهشون دست بزنید. برای اینکه این label رو specialize کنید چه راهی پیشنهاد میدهید؟
سلام دوست عزیز.
به نظر بهترین راه ارث بری هست. در ضمن ترد شما کار خودش رو می کنه، و تغییراتی که در کلاس فرزند می دهید، تاثیری روی ترد شما ندارد. مگر اینکه شما بخواهید تغییراتی اعمال کنید که باعث تغییری در ترد شود ( متغیری که ترد از آن استفاده می کند) که آن هم یا مقدار پیش فرض دارد یا باید با استفاده از سازنده کلاس پایه آن مقدار را مقدار دهی کنید. شما نمی توانید یک متغیر از کلاس والد را که جزءی از خصوصیات آن کلاس است را تغییر دهید. چون اصولا باید Private باشد و شما به private های یک کلاس دسترسی ندارید. فکر نمی کنم تغییراتی که می خواهید اعمال کنید تاثیری بر روی ترد داشته باشد. اگر باز هم تاثیری دارد لطفا کد را بگذارید تا بهتر بتوانیم بحث را ادامه دهیم.
یا علی!
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.