У меня возникает проблема с некоторыми попытками чтения одной и той же переменной в многопоточности сокетов, когда я не могу поделиться ею между потоками.
Это работает как приложение, где работодатель назначает работу дляработник.Через свой интерфейс работодатель может добавлять и присваивать ArrayList внутри класса с именем ListadoPedidos.
Когда ServerSocket работодателя принимает сокет сотрудника, он запускает TCP-соединение и запускает следующий поток:
public class HiloServer implements Runnable{
private ListadoPedidos peds=new ListadoPedidos();
private ListadoOperarios operarios=new ListadoOperarios();
private ListadoSockets sockets=new ListadoSockets();
private SocketServer s;
public HiloServer(SocketServer sock, JFrame frame, ListadoPedidos pedidos) {
s=sock;
peds=pedidos;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
boolean agregar;
Socket nuevo;
try {
while(true) {
// ACEPTA OPERARIOS QUE DESEEN CONECTARSE
s.aceptar();
nuevo=s.getSocket();
sockets.addSocket(nuevo);
new NuevoCliente();
HiloDatos hd=new HiloDatos(s, nuevo,operarios,peds,sockets);
Thread t=new Thread(hd);
t.start();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
* обратите внимание, что я отправляю объект, в котором хранятся добавленные добавления.
Затем он запускает другой поток, который будет работать как своего рода «проверка»для номера сотруднику приходится вставлять и отправлять через интерфейс Swing, чтобы действительно войти в систему.Этот поток создается каждый раз, когда новый сотрудник сокета устанавливает TCP-соединение с работодателем ServerSocket.Это идет как:
public class HiloDatos implements Runnable {
private int n;
private Socket cliente;
private SocketServer server;
private int opRecibido;
private ListadoOperarios ops;
private ListadoPedidos peds;
private ListadoSockets socks;
public HiloDatos(SocketServer ss, Socket nuevo, ListadoOperarios operarios, ListadoPedidos pedidos, ListadoSockets sockets) {
cliente=nuevo;
server=ss;
ops=operarios;
peds=pedidos;
socks=sockets;
}
@Override
public void run() {
server.setSocket(cliente);
boolean agregar, aceptado=false;
try {
do {
// RECIBE EL NRO OPERARIO Y VERIFICA SU EXISTENCIA
agregar=true;
opRecibido=Integer.parseInt(server.recibir());
for(int c=0;c<ops.getOperarios().size();c++) {
if (opRecibido==ops.getOperarios().get(c)) {
new ErrorRepetido();
agregar=false;break;
}
}
if (agregar==true) {
ops.addOperarios(opRecibido);
server.enviar("Si");
aceptado=true;
}
}while(aceptado==false);
HiloPedidos hp=new HiloPedidos(server,opRecibido,ops,peds,socks);
Thread t=new Thread(hp);
t.start();
}catch (NumberFormatException e) {
new ErrorDatos();
} catch (ConnectException e) {
new ErrorConexion();
} catch (SocketException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(cliente));
cliente.close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnSocket();
} catch (IOException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(cliente));
cliente.close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnFlujo();
}
}
}
И, наконец, он запускает еще один поток, который ищет тот же номер проверки из потока выше в ArrayList присвоений ("pedidos" класса ListadoPedidos), от которого я продолжал передаватьпоток в поток, и если он находит «новый», он должен отправить его в подключенный сокет:
public class HiloPedidos implements Runnable {
private Pedido ped;
private SocketServer server;
private int op;
private ListadoOperarios ops;
private ListadoPedidos peds;
private ListadoSockets socks;
public HiloPedidos(SocketServer ss, int opRecibido, ListadoOperarios operarios, ListadoPedidos pedidos, ListadoSockets sockets) {
server=ss;
opRecibido=op;
ops=operarios;
peds=pedidos;
socks=sockets;
}
@Override
public void run() {
int cambio=0, nuevo;
Pedido pedRecibido;
try {
while(true) {
// ENVÍA PEDIDOS
nuevo=peds.Contar(op);
if(nuevo==cambio) {
cambio=peds.Contar(op);
pedRecibido=peds.TraerNuevo(op, cambio);
server.enviarObjeto(pedRecibido);
}
}}
catch (NumberFormatException e) {
new ErrorDatos();
} catch (ConnectException e) {
new ErrorConexion();
} catch (SocketException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(server.getSocket()));
server.getSocket().close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnSocket();
} catch (IOException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(server.getSocket()));
server.getSocket().close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnFlujo();
}
}
}
Проблема в том, что последний поток не может действительно заметить изменение в списке, так как я отлаживал его и никогда не достигал точки останова внутри условия отправки назначения.Класс ListadoPedidos выглядит следующим образом:
public class ListadoPedidos {
private static volatile ArrayList<Pedido> pedidos=new ArrayList<>();
public ListadoPedidos() {
}
public ArrayList<Pedido> getPedidos() {
return pedidos;
}
public synchronized void addPedidos(Pedido pedido) {
pedidos.add(pedido);
}
public int Contar(int o) {
int n=0;
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
}
return n;
}
public Pedido TraerNuevo(int o, int c) {
int n=0;
Pedido nuevo = new Pedido();
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
if (n==c) {
nuevo=p;break;
}
}
return nuevo;
}
}
Contar - это тот, который учитывает назначение со значением nrooperario, равным значению, которое он приносит из потока, а TraerNuevo приносит назначение, которое должно быть отправлено (никогда не достигалось этогометод).
Я пытался объявить ArrayList как volatile и все, но ничего не работает.Имейте в виду, что даже если я использую сокетные соединения, проблема больше связана с общим varaible, который не может обновляться между потоками.Любая помощь будет оценена.